检测2个字符串中第一个差异的位置

gal*_*lki 4 javascript string-matching

在Javascript中找到任何两个字符串中第一个差异的位置的最简洁方法是什么?

var a = 'in the';
var b = 'in he';
findFirstDiffPos(a, b); // 3

var c = 'in the beginning';
findFirstDiffPos(a, c); // 6 
Run Code Online (Sandbox Code Playgroud)

Yel*_*yev 8

您可以简单地遍历字符串并逐个字符地检查它。

document.body.innerHTML += findFirstDiffPos("in he", "in the") + "<br/>";
document.body.innerHTML += findFirstDiffPos("abcd", "abcde") + "<br/>";
document.body.innerHTML += findFirstDiffPos("zxc", "zxc");

function findFirstDiffPos(a, b)
{
   var shorterLength = Math.min(a.length, b.length);

   for (var i = 0; i < shorterLength; i++)
   {
       if (a[i] !== b[i]) return i;
   }

   if (a.length !== b.length) return shorterLength;

   return -1;
}
Run Code Online (Sandbox Code Playgroud)

输出是3 4 -1::
3因为字符串在位置 3 处不同
4:字符串abcd是 的前缀abcde,但它们的长度不同。string 中不存在第 4 个(从 0 开始)字符abcd。您可以根据您的要求更改此逻辑
-1:字符串相等

更新:正如@torazaburo 在评论中提到的,代码可以更简单 - 只需循环直到Math.max()它们的长度。它会起作用,因为s[i]fori >= s.length将返回undefined并且条件将导致true.

document.body.innerHTML += findFirstDiffPos("in he", "in the") + "<br/>";
document.body.innerHTML += findFirstDiffPos("abcd", "abcde") + "<br/>";
document.body.innerHTML += findFirstDiffPos("zxc", "zxc");

function findFirstDiffPos(a, b)
{
  var longerLength = Math.max(a.length, b.length);
  for (var i = 0; i < longerLength; i++)
  {
     if (a[i] !== b[i]) return i;
  }

  return -1;
}
Run Code Online (Sandbox Code Playgroud)


小智 7

循环

循环方法可以更简洁地编写

function findFirstDiffPos(a, b) {
  var i = 0;
  if (a === b) return -1;
  while (a[i] === b[i]) i++;
  return i;
}
Run Code Online (Sandbox Code Playgroud)

根据jsperf的说法,这种替代方案比其他方案快5-20倍.

Array#findIndex

由于我们试图找到某个条件所在的索引,这似乎是一个完美的应用程序findIndex:

function findFirstDiffPos(a, b) {
  if (a.length < b.length) [a, b] = [b, a];
  return [...a].findIndex((chr, i) => chr !== b[i]);
}
Run Code Online (Sandbox Code Playgroud)

(我们需要更长的数组作为我们查找的数组,因此我们在必要时反转顺序.我们使用[...a]将字符串转换为字符数组.)

免责声明:这是一个ES6界面,您必须在IE上填充(但不是Edge).

这种替代方案比直线环路慢20倍.

递归

只是为了好玩,这是一个递归的解决方案:

function findFirstDiffPos(a, b) {
  return function _iterate([headA, ...tailA], [headB, ...tailB], n) {
    return headA !== headB ? n : headA === undefined) ? -1 : _iterate(tailA, tailB, n+1);
  }(a.split(''), b.split(''), 0);
}
Run Code Online (Sandbox Code Playgroud)

正则表达式

同样在"只是为了好玩"类别中,一个正则表达式解决方案.我们/^(a(b(c)?)?)?/将从一个字符串构造一个表单的正则表达式,并将其与另一个字符串匹配,并检查匹配的长度.

function make_regexp(str) {
  var result = '';
  for (var i = str.length-1; i >= 0; i--)
    result = '(' + str[i] + result + ')?';
  return '^' + result;
}

function findFirstDiffPos(a, b) {
  return a === b ? -1 : b.match(make_regexp(a))[0].length;
}
Run Code Online (Sandbox Code Playgroud)

即使我们预编译正则表达式,这仍然比普通的旧循环慢五倍.