JavaScript字符串差异高亮问题:如何识别被删除的字符?
修正字符串对比中的删除字符高亮问题
现有方案仅能正确识别并高亮新增字符,但遇到字符被删除的场景时,高亮逻辑会失效。以下是原代码:
原JavaScript代码
function highlightDifferences(newValue, oldValue) { if (oldValue === '' || newValue === oldValue) // Just return if the old value is empty or if the two values match return newValue; var highlightedCharacter = ""; // returnText will be modifed below var oldValueArray = oldValue.split(''); var newValueArray = newValue.split(''); var returnArray = []; for (var x = 0; x < newValue.split('').length; x++) { if (oldValueArray[0] !== undefined && oldValueArray[0] === newValueArray[0]) { returnArray.push(newValueArray[0]); // add the un-highlighted character to the return array oldValueArray.shift(); // if the two characters are the same, drop them and move to the next character for comparison newValueArray.shift(); } else { highlightedCharacter = '<span class="highlight">' + newValueArray[0] + '</span>'; returnArray.push(highlightedCharacter); // add the highlighted character to the return array newValueArray.shift(); // remove the unmatched character from the array. oldValueArray is unchanged to compare to the next character in the newValue array } } return returnArray.join(''); } var oldValue = document.getElementById("oldValue").innerText; var newValue = document.getElementById("newValue").innerText; var text = highlightDifferences(newValue,oldValue); document.getElementById("compared").innerHTML = text; var oldValue2 = document.getElementById("oldValue2").innerText; var newValue2 = document.getElementById("newValue2").innerText; var text = highlightDifferences(newValue2,oldValue2); document.getElementById("compared2").innerHTML = text;
原CSS代码
.highlight { background-color: #fdff674d; color: red; }
原HTML代码
<div><strong>Old:</strong> <span id="oldValue">https://somedomain.info/ac834b89e</span></div> <div><strong>New:</strong> <span id="newValue">https://55some5domain.i555nfo/ac834b89e</span></div> <div><strong>Show Added characters: </strong><span id="compared">to be replaced</span></div> <hr /> <div><strong>Old:</strong> <span id="oldValue2">https://somedomain.info/ac834b89e</span></div> <div><strong>New:</strong> <span id="newValue2">https://55some.i555nfo/ac834b89e</span></div> <div><strong>Result with removed characters: </strong><span id="compared2">to be replaced</span></div>
解决方案:基于向前查找的匹配逻辑
核心思路
原逻辑仅从数组头部逐一匹配,遇到不相等字符直接标记为新增,完全忽略了旧字符串中存在但新字符串缺失的字符(即删除操作)。我们需要调整逻辑:
- 当当前字符不匹配时,在新字符串的剩余部分向前查找是否存在与旧字符串当前字符匹配的项
- 如果找到匹配项:说明中间的旧字符已被删除,将这些删除的字符标记为删除样式,同时跳过旧数组中这些已删除的项
- 如果未找到匹配项:说明当前新字符是新增的,标记为新增样式
修正后的完整代码
JavaScript(核心逻辑修改)
function highlightDifferences(newValue, oldValue) { if (oldValue === '' || newValue === oldValue) { return newValue; } const oldArr = oldValue.split(''); const newArr = newValue.split(''); const result = []; let oldIndex = 0; let newIndex = 0; while (oldIndex < oldArr.length || newIndex < newArr.length) { // 情况1:当前字符匹配,直接加入结果 if (oldIndex < oldArr.length && newIndex < newArr.length && oldArr[oldIndex] === newArr[newIndex]) { result.push(newArr[newIndex]); oldIndex++; newIndex++; } else { // 向前查找新数组中是否存在匹配当前旧字符的位置 const foundIndex = newArr.slice(newIndex).indexOf(oldArr[oldIndex]); if (foundIndex !== -1 && oldIndex < oldArr.length) { // 找到匹配:说明newIndex到newIndex+foundIndex之间的是新增字符 for (let i = newIndex; i < newIndex + foundIndex; i++) { result.push(`<span class="highlight-added">${newArr[i]}</span>`); } // 匹配的字符直接加入 result.push(newArr[newIndex + foundIndex]); oldIndex++; newIndex += foundIndex + 1; } else { // 未找到匹配:分两种情况,要么是新字符新增,要么是旧字符被删除 if (newIndex < newArr.length) { // 新字符是新增 result.push(`<span class="highlight-added">${newArr[newIndex]}</span>`); newIndex++; } if (oldIndex < oldArr.length) { // 旧字符被删除,标记为删除样式 result.push(`<span class="highlight-deleted">${oldArr[oldIndex]}</span>`); oldIndex++; } } } } return result.join(''); } // 执行对比 const oldValue = document.getElementById("oldValue").innerText; const newValue = document.getElementById("newValue").innerText; document.getElementById("compared").innerHTML = highlightDifferences(newValue, oldValue); const oldValue2 = document.getElementById("oldValue2").innerText; const newValue2 = document.getElementById("newValue2").innerText; document.getElementById("compared2").innerHTML = highlightDifferences(newValue2, oldValue2);
CSS(新增删除样式)
/* 新增字符高亮 */ .highlight-added { background-color: #fdff674d; color: red; } /* 删除字符高亮(划掉样式) */ .highlight-deleted { text-decoration: line-through; color: #888; }
HTML(修正原标签错误)
<div><strong>Old:</strong> <span id="oldValue">https://somedomain.info/ac834b89e</span></div> <div><strong>New:</strong> <span id="newValue">https://55some5domain.i555nfo/ac834b89e</span></div> <div><strong>新增字符高亮结果: </strong><span id="compared">to be replaced</span></div> <hr /> <div><strong>Old:</strong> <span id="oldValue2">https://somedomain.info/ac834b89e</span></div> <div><strong>New:</strong> <span id="newValue2">https://55some.i555nfo/ac834b89e</span></div> <div><strong>含删除字符的高亮结果: </strong><span id="compared2">to be replaced</span></div>
内容的提问来源于stack exchange,提问作者Adam Hey
相关产品推荐
相关产品推荐

