是否有一种方法可以在JavaScript中返回两个数组之间的差异?

例如:

var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];

// need ["c", "d"]

当前回答

我想要一个类似的函数,它接受一个旧数组和一个新数组,并给我一个添加项的数组和一个删除项的数组,我希望它是有效的(所以没有.contains!)。

你可以在这里尝试我提出的解决方案:http://jsbin.com/osewu3/12。

有人能看出算法的问题或改进吗?谢谢!

代码清单:

function diff(o, n) {
  // deal with empty lists
  if (o == undefined) o = [];
  if (n == undefined) n = [];

  // sort both arrays (or this won't work)
  o.sort(); n.sort();

  // don't compare if either list is empty
  if (o.length == 0 || n.length == 0) return {added: n, removed: o};

  // declare temporary variables
  var op = 0; var np = 0;
  var a = []; var r = [];

  // compare arrays and add to add or remove lists
  while (op < o.length && np < n.length) {
      if (o[op] < n[np]) {
          // push to diff?
          r.push(o[op]);
          op++;
      }
      else if (o[op] > n[np]) {
          // push to diff?
          a.push(n[np]);
          np++;
      }
      else {
          op++;np++;
      }
  }

  // add remaining items
  if( np < n.length )
    a = a.concat(n.slice(np, n.length));
  if( op < o.length )
    r = r.concat(o.slice(op, o.length));

  return {added: a, removed: r}; 
}

其他回答

您可以使用一个公共对象并计算第一个数组中每个值的频率。对于第二个数组,减少公共对象中的值。然后遍历所有键并添加所有值大于1的键。

常量差值= (a1, a2) => { Var obj = {}; a1。forEach(obj[v] = (obj[v] || 0) + 1); a2。forEach(v => obj[v] = (obj[v] || 0) - 1); 返回对象 . keys (obj) .reduce((r,k) => { If (obj[k] > 0) r = r.concat (Array.from({长度:obj [k]}) .fill (k)); 返回r; }, []); }; const =结果不同([' a ', ' ', ' b ', ' c ', ' d '], [a, b]); console.log(结果);

function diff(arr1, arr2) {
  var filteredArr1 = arr1.filter(function(ele) {
    return arr2.indexOf(ele) == -1;
  });

  var filteredArr2 = arr2.filter(function(ele) {
    return arr1.indexOf(ele) == -1;
  });
  return filteredArr1.concat(filteredArr2);
}

diff([1, "calf", 3, "piglet"], [1, "calf", 3, 4]); // Log ["piglet",4]

ES6中一个更简洁的方法是以下解决方案。

var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];

区别

a2.filter(d => !a1.includes(d)) // gives ["c", "d"]

十字路口

a2.filter(d => a1.includes(d)) // gives ["a", "b"]

析取联合(对称差分)

[ ...a2.filter(d => !a1.includes(d)),
  ...a1.filter(d => !a2.includes(d)) ]

使用ES7有一个更好的方法:


十字路口

 let intersection = arr1.filter(x => arr2.includes(x));

对于[1,2,3][2,3],它将生成[2,3]。另一方面,for[1,2,3][2,3,5]将返回相同的结果。


区别

let difference = arr1.filter(x => !arr2.includes(x));

对于[1,2,3][2,3],它将生成[1]。另一方面,for[1,2,3][2,3,5]将返回相同的结果。


对于对称差分,你可以这样做:

let difference = arr1
                 .filter(x => !arr2.includes(x))
                 .concat(arr2.filter(x => !arr1.includes(x)));

通过这种方式,您将得到一个包含arr1中所有不在arr2中的元素的数组,反之亦然

正如@Joshaven Potter在他的回答中指出的,你可以把这个添加到Array中。原型,所以它可以这样使用:

Array.prototype.diff = function(arr2) { return this.filter(x => !arr2.includes(x)); }
[1, 2, 3].diff([2, 3])
var result = [];
var arr1 = [1,2,3,4];
var arr2 = [2,3];
arr1.forEach(function(el, idx) {
    function unEqual(element, index, array) {
        var a = el;
        return (element!=a);
    }
    if (arr2.every(unEqual)) {
        result.push(el);
    };
});
alert(result);