对于模棱两可的标题感到非常抱歉,因为我根本不知道如何用一行描述我的问题。
我有一个以随机间隔不断变化的字符串。我希望能够跟踪该字符串的更改,然后能够重建最终的字符串。
示例:
const text1 = 'Hello everyone, my name is Chris';
//12 seconds later it turns into:
const text2 = 'Hello everyone, my fame is gone';
//... Keeps changing...
我正在使用这个名为 fast-diff 的优秀库来比较字符串并存储 diff 数组。这是它的工作原理:
const text1 = 'Hello everyone, my name is Chris';
const text2 = 'Hello everyone, my fame is gone';
const diff_array = diff(text1, text2, 1);
console.log(diff_array);
结果是:
[
[ 0, 'Hello everyone, my ' ],
[ -1, 'n' ],
[ 1, 'f' ],
[ 0, 'ame is ' ],
[ -1, 'Chris' ],
[ 1, 'gone' ]
]
其中 0 表示未更改的字符,1 表示添加的字符,-1 表示删除的字符。
基于这个 diff 数组,我可以通过运行如下命令轻松重建
'Hello everyone, my fame is gone'
:
diff_array.forEach(el => {
if(el[0] !== -1)
process.stdout.write(el[1]);
})
我要做的就是将数组存储在某个地方。
问题:在处理大字符串时,当前构建的 diff 数组会存储大量冗余,因为大多数时候对 10,000 个字符串的更改是最小的。
目标:我想做的是存储原始字符串并从
转换差异数组[
[ 0, 'Hello everyone, my ' ],
[ -1, 'n' ],
[ 1, 'f' ],
[ 0, 'ame is ' ],
[ -1, 'Chris' ],
[ 1, 'gone' ]
]
至:
[
[
0,
{
start: 0,
end: 19
}
],
[ -1, 'n' ],
[ 1, 'f' ],
[
0,
{
start: 20,
end: 27
}
],
[-1, 'Chris' ],
[ 1, 'gone' ]
]
其中 0 代替 参考未更改的原始文本的开始和结束字符位置。这将大大降低我的存储成本。我需要一个函数来接受原始文本和 diff 数组,并吐出一个与上面类似的新 diff 数组。
我在这里苦苦挣扎的原因是因为在原始字符串中搜索
'Hello everyone, my '
和 'ame is '
并找到它们的位置并不是一个简单的问题,因为这些子字符串也可以在其他地方。我必须按顺序搜索它,同时跟踪当前搜索位置在哪里。
从 fast-diff 返回的差异有额外的信息,您不需要从原始数据中重建,可能会出于验证目的而保留。因此,您可以做的就是将它们删除,基本上对于删除和复制操作,只需存储一个数字,而这只是您需要保留字符串的添加操作。
例如。您展示的示例 diff 可以直接制作为 ->
[[0,19],[-1,1],[1,"f"],[0,7],[-1,5],[1,"gone"]]
下面是使用此技术的工作片段。
function makeShortDifs(d) {
return d.map(m => {
let [action, value] = m;
if (action !== 1) value = value.length;
return [action, value];
});
}
function makeNew(o, difs) {
let n = '', p = 0;
for (const d of difs) {
const [action, value] = d;
if (action === 0) {
n += o.slice(p, p + value);
p += value;
} else if (action === 1) {
n += value;
} else p += value;
}
return n;
}
///Test...
//difs we get from fast-diff
const bigDifs = [
[ 0, 'Hello everyone, my ' ],
[ -1, 'n' ],
[ 1, 'f' ],
[ 0, 'ame is ' ],
[ -1, 'Chris' ],
[ 1, 'gone' ]
];
//make our diffs smalll
const smallDifs = makeShortDifs(bigDifs);
//now test small diffs on original text.
const original = 'Hello everyone, my name is Chris';
console.log(original);
console.log(makeNew(original, smallDifs));