在 JavaScript 中找出两个字符串之间的差异

问题描述 投票:0回答:7

我需要找出两个字符串之间的区别。

const string1 = 'lebronjames';
const string2 = 'lebronnjames';

预期的输出是找到额外的

n
并将其记录到控制台。

有没有办法在 JavaScript 中做到这一点?

javascript string algorithm difference
7个回答
12
投票

另一个选项,用于更复杂的差异检查,是使用 PatienceDiff 算法。我将这个算法移植到 Javascript 中......

https://github.com/jonTrent/PatienceDiff

...虽然该算法通常用于文本的逐行比较(例如计算机程序),但它仍然可以用于逐字符的比较。例如,要比较两个字符串,您可以执行以下操作...

let a = "thelebronnjamist";
let b = "the lebron james";

let difference = patienceDiff( a.split(""), b.split("") );

...将

difference.lines
设置为具有比较结果的数组...

difference.lines: Array(19)

0: {line: "t", aIndex: 0, bIndex: 0}
1: {line: "h", aIndex: 1, bIndex: 1}
2: {line: "e", aIndex: 2, bIndex: 2}
3: {line: " ", aIndex: -1, bIndex: 3}
4: {line: "l", aIndex: 3, bIndex: 4}
5: {line: "e", aIndex: 4, bIndex: 5}
6: {line: "b", aIndex: 5, bIndex: 6}
7: {line: "r", aIndex: 6, bIndex: 7}
8: {line: "o", aIndex: 7, bIndex: 8}
9: {line: "n", aIndex: 8, bIndex: 9}
10: {line: "n", aIndex: 9, bIndex: -1}
11: {line: " ", aIndex: -1, bIndex: 10}
12: {line: "j", aIndex: 10, bIndex: 11}
13: {line: "a", aIndex: 11, bIndex: 12}
14: {line: "m", aIndex: 12, bIndex: 13}
15: {line: "i", aIndex: 13, bIndex: -1}
16: {line: "e", aIndex: -1, bIndex: 14}
17: {line: "s", aIndex: 14, bIndex: 15}
18: {line: "t", aIndex: 15, bIndex: -1}

凡是

aIndex === -1
bIndex === -1
的地方都表示两个字符串之间的差异。具体...

  • 元素3表示在
    b
    位置3找到字符“”。
  • 元素10表示在
    a
    位置9找到字符“n”。
  • 元素11表示在
    b
    位置10找到字符“”。
  • 元素15表示在
    a
    的第13位找到了字符“i”。
  • 元素16表示在
    b
    位置14找到字符“e”。
  • 元素18表示在
    a
    的第15位找到字符“t”。

请注意,PatienceDiff 算法对于比较两个相似的文本块或字符串非常有用。它不会告诉您是否进行了基本编辑。例如,以下...

let a = "james lebron";
let b = "lebron james";

let difference = patienceDiff( a.split(""), b.split("") );

...返回

difference.lines
包含...

difference.lines: Array(18)

0: {line: "j", aIndex: 0, bIndex: -1}
1: {line: "a", aIndex: 1, bIndex: -1}
2: {line: "m", aIndex: 2, bIndex: -1}
3: {line: "e", aIndex: 3, bIndex: -1}
4: {line: "s", aIndex: 4, bIndex: -1}
5: {line: " ", aIndex: 5, bIndex: -1}
6: {line: "l", aIndex: 6, bIndex: 0}
7: {line: "e", aIndex: 7, bIndex: 1}
8: {line: "b", aIndex: 8, bIndex: 2}
9: {line: "r", aIndex: 9, bIndex: 3}
10: {line: "o", aIndex: 10, bIndex: 4}
11: {line: "n", aIndex: 11, bIndex: 5}
12: {line: " ", aIndex: -1, bIndex: 6}
13: {line: "j", aIndex: -1, bIndex: 7}
14: {line: "a", aIndex: -1, bIndex: 8}
15: {line: "m", aIndex: -1, bIndex: 9}
16: {line: "e", aIndex: -1, bIndex: 10}
17: {line: "s", aIndex: -1, bIndex: 11}

请注意,PatienceDiff 不报告名字和姓氏的交换,而是提供一个结果,显示从

a
中删除了哪些字符以及向
b
添加了哪些字符,最终得到
b 的结果
.

编辑:添加了名为patienceDiffPlus的新算法。

在仔细研究上面提供的最后一个示例后,该示例显示了 PatienceDiff 在识别可能移动的线条方面的局限性,我突然意识到有一种优雅的方法可以使用 PatienceDiff 算法来确定是否有任何线条确实可能移动而不仅仅是显示删除和添加。

简而言之,我在 PatienceDiff.js 文件的底部添加了

patienceDiffPlus
算法(到上面标识的 GitHub 存储库)。
patienceDiffPlus
算法从初始
patienceDiff
算法中取出删除的aLines[]和添加的bLines[],并再次通过
patienceDiff
算法运行它们。即,
patienceDiffPlus
正在寻找可能移动的线的最长公共子序列,因此它将其记录在原始的
patienceDiff
结果中。
patienceDiffPlus
算法继续此操作,直到找不到更多移动的行。

现在,使用

patienceDiffPlus
,下面的比较...

let a = "james lebron";
let b = "lebron james";

let difference = patienceDiffPlus( a.split(""), b.split("") );

...返回

difference.lines
包含...

difference.lines: Array(18)

0: {line: "j", aIndex: 0, bIndex: -1, moved: true}
1: {line: "a", aIndex: 1, bIndex: -1, moved: true}
2: {line: "m", aIndex: 2, bIndex: -1, moved: true}
3: {line: "e", aIndex: 3, bIndex: -1, moved: true}
4: {line: "s", aIndex: 4, bIndex: -1, moved: true}
5: {line: " ", aIndex: 5, bIndex: -1, moved: true}
6: {line: "l", aIndex: 6, bIndex: 0}
7: {line: "e", aIndex: 7, bIndex: 1}
8: {line: "b", aIndex: 8, bIndex: 2}
9: {line: "r", aIndex: 9, bIndex: 3}
10: {line: "o", aIndex: 10, bIndex: 4}
11: {line: "n", aIndex: 11, bIndex: 5}
12: {line: " ", aIndex: 5, bIndex: 6, moved: true}
13: {line: "j", aIndex: 0, bIndex: 7, moved: true}
14: {line: "a", aIndex: 1, bIndex: 8, moved: true}
15: {line: "m", aIndex: 2, bIndex: 9, moved: true}
16: {line: "e", aIndex: 3, bIndex: 10, moved: true}
17: {line: "s", aIndex: 4, bIndex: 11, moved: true}

注意添加了

moved
属性,它标识一行(或本例中的字符)是否可能被移动。同样,
patienceDiffPlus
只是匹配删除的 aLines[] 和添加的 bLines[],因此不能保证这些行确实被移动了,但很有可能它们确实被移动了。


10
投票

这将返回两个字符串之间的第一个差异

喜欢

lebronjames
lebronnjames
n

const string1 = 'lebronjames';
const string2 = 'lebronnjabes';


const findFirstDiff = (str1, str2) =>
  str2[[...str1].findIndex((el, index) => el !== str2[index])];


// equivalent of 

const findFirstDiff2 = function(str1, str2) {
  return str2[[...str1].findIndex(function(el, index) {
    return el !== str2[index]
  })];
}



console.log(findFirstDiff2(string1, string2));
console.log(findFirstDiff(string1, string2));


5
投票

    function getDifference(a, b)
    {
        var i = 0;
        var j = 0;
        var result = "";

        while (j < b.length)
        {
         if (a[i] != b[j] || i == a.length)
             result += b[j];
         else
             i++;
         j++;
        }
        return result;
    }
    console.log(getDifference("lebronjames", "lebronnjames"));


4
投票

对于那些想要返回两个字符串之间的first差异的人可以这样调整:

排序和查找

const getDifference = (s, t) => {
  s = [...s].sort();
  t = [...t].sort();
  return t.find((char, i) => char !== s[i]);
};

console.log(getDifference('lebronjames', 'lebronnjames'));
console.log(getDifference('abc', 'abcd'));

添加字符代码

const getDifference = (s, t) => {
  let sum = t.charCodeAt(t.length - 1);
  for (let j = 0; j < s.length; j++) {
    sum -= s.charCodeAt(j);
    sum += t.charCodeAt(j);
  }
  return String.fromCharCode(sum);
};

console.log(getDifference('lebronjames', 'lebronnjames'));
console.log(getDifference('abc', 'abcd'));


1
投票
function findDifference(s, t) {

  if(s === '') return t;

  
  
  // this is useless and can be omitted.
  for(let i = 0; i < t.length; i++) {
    if(!s.split('').includes(t[i])) {
      return t[i];
    }
  }
  // this is useless and can be omitted.


  
  // (if the additional letter exists)
  // cache them, count values, different values of the same letter would give the answer.

  const obj_S = {};
  const obj_T = {};

  for(let i = 0; i < s.length; i++) {
    if(!obj_S[s[i]]) {
      obj_S[s[i]] = 1;
    }else {
      obj_S[s[i]]++;
    }
  }
  
  for(let i = 0; i < t.length; i++) {
    if(!obj_T[t[i]]) {
      obj_T[t[i]] = 1;
    }else {
      obj_T[t[i]]++;
    }
  }

  for(const key in obj_T) {
    if(obj_T[key] !== obj_S[key]) {
      return key
    }
  }

}

// if more than 1 letter -> store the values and the return, logic stays the same.

console.log(findDifference('john', 'johny')) // --> y
console.log(findDifference('bbcc', 'bbbcc')) //--> b

实际上第一部分可以省略(第一个for循环)我对边缘情况的解决方案解决了整个问题,因为如果该值不存在它将是未定义的并且计数!==未定义将返回字母...


1
投票

var findTheDifference = function(s, t) {
  let res = [...s].sort();
  let res1 = [...t].sort();
  let j = 0;
  while (j < res1.length) {
    if (res[j] != res1[j]) {
      return res1[j];
    }
    j++;
  }
};

console.log(findTheDifference("a", "aa"))


0
投票

我获取两个字符串之间差异的方法。我希望这个功能对某人有所帮助:

function getDifferences(a, b){
  
  let result = {
    state : true,
    diffs : []
  }

  if(a===b) return result;
  
  result.state = false;

  for (let index = 0; index < a.length; index++) {
    if (a[index] !== b[index]) {
        result.diffs.push({index: index, old: a[index], new: b[index]})
    }
  }
  
  return result;
}
© www.soinside.com 2019 - 2024. All rights reserved.