如何将fast-diff生成的diff数组转换为基于原字符串位置的精简格式
优化fast-diff结果存储:用原字符串位置替换重复文本
问题场景
我有一个会随机变化的大字符串,需要跟踪其变更并重建最终内容。目前使用fast-diff库生成diff数组,但当原字符串很大(比如10000字符)而变更很少时,diff数组里类型为0(未更改)的条目会存储大量重复文本,造成冗余。
原diff格式示例
原字符串:Hello everyone, my name is Chris
变更后字符串:Hello everyone, my fame is gone
fast-diff生成的原diff数组:
[ [ 0, 'Hello everyone, my ' ], [ -1, 'n' ], [ 1, 'f' ], [ 0, 'ame is ' ], [ -1, 'Chris' ], [ 1, 'gone' ] ]
目标优化格式
希望把类型0的条目替换为原字符串的起止位置引用,减少存储成本,优化后的diff数组:
[ [0, { start: 0, end: 19 }], [-1, 'n'], [1, 'f'], [0, { start: 20, end: 27 }], [-1, 'Chris'], [1, 'gone'] ]
实现函数
核心逻辑是按顺序跟踪原字符串的当前偏移位置,避免直接搜索子串导致的重复匹配问题。函数遍历原diff数组,根据条目类型更新偏移量并转换格式:
function convertDiffToPositionRefs(originalText, diffArray) { const convertedDiff = []; let currentOffset = 0; for (const [type, content] of diffArray) { if (type === 0) { // 未更改内容:计算起止位置 const start = currentOffset; const end = currentOffset + content.length; convertedDiff.push([0, { start, end }]); // 更新偏移量:原字符串中这段内容已处理完 currentOffset = end; } else if (type === -1) { // 删除内容:直接保留,偏移量加上删除的长度 convertedDiff.push([-1, content]); currentOffset += content.length; } else if (type === 1) { // 新增内容:直接保留,偏移量不变(新增内容不在原字符串里) convertedDiff.push([1, content]); } } return convertedDiff; }
测试示例
const originalText = 'Hello everyone, my name is Chris'; const originalDiff = [ [ 0, 'Hello everyone, my ' ], [ -1, 'n' ], [ 1, 'f' ], [ 0, 'ame is ' ], [ -1, 'Chris' ], [ 1, 'gone' ] ]; const optimizedDiff = convertDiffToPositionRefs(originalText, originalDiff); console.log(optimizedDiff); // 输出与目标格式一致
验证重建功能
从优化后的diff数组和原字符串重建最终字符串:
function reconstructFinalText(originalText, optimizedDiff) { let finalText = ''; for (const [type, data] of optimizedDiff) { if (type === 0) { // 从原字符串截取对应位置的内容 finalText += originalText.slice(data.start, data.end); } else if (type === 1) { // 新增内容直接追加 finalText += data; } // 删除内容忽略,因为重建最终字符串不需要 } return finalText; } console.log(reconstructFinalText(originalText, optimizedDiff)); // 输出:Hello everyone, my fame is gone
内容的提问来源于stack exchange,提问作者codemonkey
相关产品推荐
相关产品推荐

