如何比较两个数组并返回差异的索引?

8
我有两个数组需要检查它们之间的差异,并返回该差异的索引。
例如,当输入值改变时,我目前有两个数组会被更新。每当输入中有新标签时,如“@testing”,就会更新newTags数组。我需要将newTags数组与oldTags数组进行比较,并返回差异的索引。
我目前正在将这两个数组转换为字符串并进行比较,但无法返回差异的索引。
var newTags = [];
var oldTags = [];

$input.on('keyup', function () {
    var newValue = $input.val();
    var pattern = /@[a-zA-Z]+/ig;
    var valueSearch = newValue.search(pattern);

    if (valueSearch >= 0) {
        newTags = newValue.match(pattern);

        if ((newTags + "") != (oldTags + "")) {
            //Need index of difference here
            console.log(newTags, oldTags);
        }

        oldTags = newTags;
    }
});

Working example


仅在数组中搜索一个值?还是搜索一个值并且它与另一个数组的索引相同? - floor
@floor - 例如,newTags 可能是 ["@testing", "@hello"],而 oldTags 可能是 ["@test", "@hello"]。因此,差异的索引为 0,因为数组中的第一个值不同。 - Fizzix
那让我更加困惑了。 - floor
@floor - 哈哈哈,那可能是我的错。我想做的就是比较newTagsoldTags,并返回数组中差异的位置。 - Fizzix
现在我想了想,一个简单的$.each循环可能是最好的解决方案... - Fizzix
我在解决方案中使用了2个循环。 - floor
4个回答

2
你可以使用筛选器同时查找不同的值和索引。
JSFiddle:https://jsfiddle.net/k0uxtnkd/
Array.prototype.diff = function(a) {
    var source = this;
    return this.filter(function(i) {
        if (a.indexOf(i) < 0) {
            diffIndexes.push(source.indexOf(i));
            return true;
        } else {
            return false;
        }
    });
};
var diffIndexes = [];
var newTags = ['a','b','c'];
var oldTags = ['c'];
var diffValues = newTags.diff(oldTags);
console.log(diffIndexes); // [0, 1]
console.log(diffValues); // ['a', 'b']

将其转换为函数而不是将其添加到数组原型中: JSFiddle: https://jsfiddle.net/k0uxtnkd/1/
function arrayDiff(a, b) {
    return a.filter(function(i) {
        if (b.indexOf(i) < 0) {
            diffIndexes.push(a.indexOf(i));
            return true;
        } else {
            return false;
        }
    });
};
var diffIndexes = [];
var newTags = ['a','b','c'];
var oldTags = ['c'];
var diffValues = arrayDiff(newTags, oldTags);
console.log(diffIndexes); // [0, 1]
console.log(diffValues); // ['a', 'b']

不错。我该如何将那个实用函数转换为普通函数? - Fizzix

2

您不需要循环遍历两个数组,可以同时循环遍历两个数组:

var findDivergence = function (a1, a2) {
    var result = [], longerLength = a1.length >= a2.length ? a1.length : a2.length;
    for (i = 0; i < longerLength; i++){
        if (a1[i] !== a2[i]) {
            result.push(i);
        }
    }
    return result;
};

console.log(findDivergence(["a","b","c","d","e","f","g","h","i"], ["a","b","d","r","e","q","g"]));
//outputs [2, 3, 5, 7, 8]

这比双重循环或使用indexOf(两者都会比必要的多次搜索第二个数组)要高效得多。 这也处理了同一项在给定数组中出现多次的情况,但是如果一个数组比另一个数组更长,并且较长的数组包含一个未定义的元素,则该索引将被视为匹配。


1
for(var i=0; i < newTags.length; i++) {
    for(var j=0; j < oldTags.length; j++) {
        if(newTags[i] === oldTags[j]) {
            console.log("match found");
            console.log("Match found for value: " + newTags[i] + " at index in oldTags: " + j + );
         }
         else{
           console.log("match not found");
         }
    }
}

使用2个循环可以进行快速检查,在if语句中添加您想要发生的内容。

0
以下是三种常见方法的性能比较,用于执行此问题中所要求的任务。
const arr1 = ['A', 'B', 'C'];
const arr2 = ['A', 'D', 'C', 'E'];

// Filter indexOf
function diffArray1(a1, a2) {
  let aDiffs = [];
  a1.filter((i) => {
    if (a2.indexOf(i) < 0) {
      aDiffs.push(a1.indexOf(i));
    }
  });
  return aDiffs;
};

// Loop indexOf
function diffArray2(a1, a2) {
  let aDiffs = [];
  for (let i=0; i<a1.length; ++i) {
    if (a2.indexOf(a1[i]) < 0) {
      aDiffs.push(a1.indexOf(a1[i]));
    }
  }
  return aDiffs;
};

// Loop equality
function diffArray3(a1, a2) {
  let aDiffs = [];
  for (let i=0; i<a1.length; ++i) {
    if (a1[i] !== a2[i]) {
      aDiffs.push(i);
    }
  }
  return aDiffs;
};

diffArray1(arr2, arr1); // Returns [1, 3]
diffArray2(arr2, arr1); // Returns [1, 3]
diffArray3(arr2, arr1); // Returns [1, 3]

diffArray3() 在我的系统上(Intel Core i7-7700HQ 32GB RAM),在 Chrome v102.0.5005.63(64位)中是最快的。 diffArray1() 大约慢了38%,diffArray2() 慢了22.5%。这是测试套件:

https://jsbench.me/59l42hhpfs/1

欢迎自由地fork这个项目并添加更多的方法;如果您这样做,请在评论中留下fork的URL。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接