如何在Javascript中获得两个数组的区别?

时间:2022-01-27 16:26:28

Is there a way to return the difference between two arrays in JavaScript?

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

For example:

例如:

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

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

Any advice greatly appreciated.

任何建议深表感谢。

56 个解决方案

#1


140  

I assume you are comparing a normal array. If not, you need to change the for loop to a for .. in loop.

我假设你在比较一个正常的数组。如果不是,则需要将for循环更改为for。在循环。

function arr_diff (a1, a2) {

    var a = [], diff = [];

    for (var i = 0; i < a1.length; i++) {
        a[a1[i]] = true;
    }

    for (var i = 0; i < a2.length; i++) {
        if (a[a2[i]]) {
            delete a[a2[i]];
        } else {
            a[a2[i]] = true;
        }
    }

    for (var k in a) {
        diff.push(k);
    }

    return diff;
}

console.log(arr_diff(['a', 'b'], ['a', 'b', 'c', 'd']));
console.log(arr_diff("abcd", "abcde"));
console.log(arr_diff("zxc", "zxc"));

A better solution, if you don't care about backward compatibility, is using filter. But still, this solution works.

如果您不关心向后兼容性,那么更好的解决方案就是使用过滤器。但是,这个解决方案仍然有效。

#2


703  

Array.prototype.diff = function(a) {
    return this.filter(function(i) {return a.indexOf(i) < 0;});
};

////////////////////  
// Examples  
////////////////////

[1,2,3,4,5,6].diff( [3,4,5] );  
// => [1, 2, 6]

["test1", "test2","test3","test4","test5","test6"].diff(["test1","test2","test3","test4"]);  
// => ["test5", "test6"]

Array.prototype.diff = function(a) {
    return this.filter(function(i) {return a.indexOf(i) < 0;});
};

////////////////////  
// Examples  
////////////////////

var dif1 = [1,2,3,4,5,6].diff( [3,4,5] );  
console.log(dif1); // => [1, 2, 6]


var dif2 = ["test1", "test2","test3","test4","test5","test6"].diff(["test1","test2","test3","test4"]);  
console.log(dif2); // => ["test5", "test6"]

Note indexOf and filter are not available in ie before ie9.

在ie9之前,注意索引和过滤器是不可用的。

#3


308  

There is a better way using ES6:

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

Intersection

十字路口

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

如何在Javascript中获得两个数组的区别?

For [1,2,3] [2,3] it will yield [2,3]. On the other hand, for [1,2,3] [2,3,5] will return the same thing.

对于[1,2,3][2,3],它将产生[2,3]。另一方面,对于[1,2,3][2,3,5]会返回相同的东西。

Difference

区别

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

如何在Javascript中获得两个数组的区别?

For [1,2,3] [2,3] it will yield [1]. On the other hand, for [1,2,3] [2,3,5] will return the same thing.

对于[1,2,3][2,3],它将产生[1]。另一方面,对于[1,2,3][2,3,5]会返回相同的东西。

For a symmetric difference, you can do:

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

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

如何在Javascript中获得两个数组的区别?

This way, you will get an array containing all the elements of arr1 that are not in arr2 and vice-versa

这样,您将得到一个包含arr1中的所有元素的数组,这些元素不在arr2中,反之亦然。

As @Joshaven Potter pointed out on his answer, you can add this to Array.prototype so it can be used like this:

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

Array.prototype.diff = arr1.filter(x => arr2.includes(x));
[1, 2, 3].diff([2, 3])

#4


285  

This is by far the easiest way to get exactly the result you are looking for, using jQuery:

这是到目前为止最简单的方法来得到您想要的结果,使用jQuery:

var diff = $(old_array).not(new_array).get();

diff now contains what was in old_array that is not in new_array

diff现在包含了在old_array中不存在于new_array中的内容。

#5


136  

The difference method in Underscore (or its drop-in replacement, Lo-Dash) can do this too:

下划线的差分方法(或它的drop-in替换,Lo-Dash)也可以这样做:

(R)eturns the values from array that are not present in the other arrays

_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
=> [1, 3, 4]

As with any Underscore function, you could also use it in a more object-oriented style:

与任何下划线函数一样,您也可以将其用于更面向对象的样式:

_([1, 2, 3, 4, 5]).difference([5, 2, 10]);

#6


57  

Plain JavaScript

There are two possible intepretations for "difference". I'll let you choose which one you want. Say you have:

有两种可能的“差异”。我会让你选择你想要的。你有说:

var a1 = ['a', 'b'     ];
var a2 = [     'b', 'c'];
  1. If you want to get ['a'], use this function:

    如果你想得到['a'],使用这个函数:

    function difference(a1, a2) {
      var result = [];
      for (var i = 0; i < a1.length; i++) {
        if (a2.indexOf(a1[i]) === -1) {
          result.push(a1[i]);
        }
      }
      return result;
    }
    
  2. If you want to get ['a', 'c'] (all elements contained in either a1 or a2, but not both -- the so-called symmetric difference), use this function:

    如果你想要得到['a', 'c'](包含在a1或a2中的所有元素,但不是两者都有,即所谓的对称差),使用这个函数:

    function symmetricDifference(a1, a2) {
      var result = [];
      for (var i = 0; i < a1.length; i++) {
        if (a2.indexOf(a1[i]) === -1) {
          result.push(a1[i]);
        }
      }
      for (i = 0; i < a2.length; i++) {
        if (a1.indexOf(a2[i]) === -1) {
          result.push(a2[i]);
        }
      }
      return result;
    }
    

Lodash / Underscore

If you are using lodash, you can use _.difference(a1, a2) (case 1 above) or _.xor(a1, a2) (case 2).

如果您使用的是lodash,您可以使用_。差异(a1, a2)(案例1)或_。xor(a1,a2)(例2)。

If you are using Underscore.js, you can use the _.difference(a1, a2) function for case 1.

如果使用下划线。js,你可以用_。不同(a1, a2)的情况1。

ES6 Set, for very large arrays

The code above works on all browsers. However, for large arrays of more than about 10,000 items, it becomes quite slow, because it has O(n²) complexity. On many modern browsers, we can take advantage of the ES6 Set object to speed things up. Lodash automatically uses Set when it's available. If you are not using lodash, use the following implementation, inspired by Axel Rauschmayer's blog post:

上面的代码适用于所有浏览器。然而,对于大型数组超过约10000件,它变得非常缓慢,因为它有O(n²)复杂性。在许多现代浏览器中,我们可以利用ES6设置对象来加快速度。Lodash在可用时自动使用Set。如果您没有使用lodash,请使用以下实现,灵感来自Axel Rauschmayer的博客文章:

function difference(a1, a2) {
  var a2Set = new Set(a2);
  return a1.filter(function(x) { return !a2Set.has(x); });
}

function symmetricDifference(a1, a2) {
  return difference(a1, a2).concat(difference(a2, a1));
}

Notes

The behavior for all examples may be surprising or non-obvious if you care about -0, +0, NaN or sparse arrays. (For most uses, this doesn't matter.)

如果您关心-0、+0、NaN或稀疏数组,那么所有示例的行为可能会令人惊讶或不明显。(在大多数情况下,这并不重要。)

#7


29  

You could use a Set in this case. It is optimized for this kind of operation (union, intersection, difference).

你可以在这个例子中使用一个集合。它对这种操作进行了优化(联合、交叉、差分)。

Make sure it applies to your case, once it allows no duplicates.

确保它适用于你的情况,一旦它不允许重复。

var a = new JS.Set([1,2,3,4,5,6,7,8,9]);
var b = new JS.Set([2,4,6,8]);

a.difference(b)
// -> Set{1,3,5,7,9}

#8


21  

function diff(a1, a2) {
  return a1.concat(a2).filter(function(val, index, arr){
    return arr.indexOf(val) === arr.lastIndexOf(val);
  });
}

Merge both the arrays, unique values will appear only once so indexOf() will be the same as lastIndexOf().

合并两个数组,唯一的值只会出现一次,所以indexOf()将与lastIndexOf()相同。

#9


17  

to subtract one array from another, simply use the snippet below:

要从另一个数组中减去一个数组,只需使用下面的代码段:

var a1 = ['1','2','3','4','6'];
var a2 = ['3','4','5'];

var items = new Array();

items = jQuery.grep(a1,function (item) {
    return jQuery.inArray(item, a2) < 0;
});

It will returns ['1,'2','6'] that are items of first array which don't exist in the second.

它将返回['1,'2','6'],这是第一个数组的项,在第二个数组中不存在。

Therefore, according to your problem sample, following code is the exact solution:

因此,根据您的问题样本,以下代码是正确的解决方案:

var array1 = ["test1", "test2","test3", "test4"];
var array2 = ["test1", "test2","test3","test4", "test5", "test6"];

var _array = new Array();

_array = jQuery.grep(array2, function (item) {
     return jQuery.inArray(item, array1) < 0;
});

#10


12  

A solution using indexOf() will be ok for small arrays but as they grow in length the performance of the algorithm approaches O(n^2). Here's a solution that will perform better for very large arrays by using objects as associative arrays to store the array entries as keys; it also eliminates duplicate entries automatically but only works with string values (or values which can be safely stored as strings):

一个使用indexOf()的解决方案对于小的数组来说是可以的,但是随着它们的长度的增长,算法的性能将接近O(n 2)。这里有一个解决方案,它将使用对象作为关联数组来将数组项存储为键,从而对非常大的数组执行得更好;它也可以自动删除重复的条目,但是只使用字符串值(或者可以安全地存储为字符串的值):

function arrayDiff(a1, a2) {
  var o1={}, o2={}, diff=[], i, len, k;
  for (i=0, len=a1.length; i<len; i++) { o1[a1[i]] = true; }
  for (i=0, len=a2.length; i<len; i++) { o2[a2[i]] = true; }
  for (k in o1) { if (!(k in o2)) { diff.push(k); } }
  for (k in o2) { if (!(k in o1)) { diff.push(k); } }
  return diff;
}

var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
arrayDiff(a1, a2); // => ['c', 'd']
arrayDiff(a2, a1); // => ['c', 'd']

#11


11  

Functional approach with ES2015

Computing the difference between two arrays is one of the Set operations. The term already indicates that the native Set type should be used, in order to increase the lookup speed. Anyway, there are three permutations when you compute the difference between two sets:

计算两个数组之间的差异是集合操作之一。这个术语已经表示应该使用本机集类型,以增加查找速度。无论如何,当你计算两组之间的差时,有三种排列:

[+left difference] [-intersection] [-right difference]
[-left difference] [-intersection] [+right difference]
[+left difference] [-intersection] [+right difference]

Here is a functional solution that reflects these permutations.

这是一个反映这些排列的功能解决方案。

Left difference:

// small, reusable auxiliary functions

const apply = f => x => f(x);
const flip = f => y => x => f(x) (y);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));


// left difference

const differencel = xs => ys => {
  const zs = createSet(ys);
  return filter(x => zs.has(x)
     ? false
     : true
  ) (xs);
};


// mock data

const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];


// run the computation

console.log( differencel(xs) (ys) );

Right difference:

differencer is trivial. It is just differencel with flipped arguments. You can write a function for convenience: const differencer = flip(differencel). That's all!

区别很简单。它只是和翻转的参数不同。您可以编写一个方便的函数:const差分= flip(不同的)。这是所有!

Symmetric difference:

Now that we have the left and right one, implementing the symmetric difference gets trivial as well:

现在我们有了左边和右边的,实现对称的差别也很简单:

// small, reusable auxiliary functions

const apply = f => x => f(x);
const flip = f => y => x => f(x) (y);
const concat = y => xs => xs.concat(y);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));


// left difference

const differencel = xs => ys => {
  const zs = createSet(ys);
  return filter(x => zs.has(x)
     ? false
     : true
  ) (xs);
};


// symmetric difference

const difference = ys => xs =>
 concat(differencel(xs) (ys)) (flip(differencel) (xs) (ys));

// mock data

const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];


// run the computation

console.log( difference(xs) (ys) );

I guess this example is a good starting point to obtain an impression what functional programming means:

我想这个例子是一个很好的起点,它可以让我们了解函数式编程的含义:

Programming with building blocks that can be plugged together in many different ways.

可以用许多不同的方式连接在一起的构建块编程。

#12


10  

With the arrival of ES6 with sets and splat operator (at the time of being works only in Firefox, check compatibility table), you can write the following one liner:

随着ES6与set和splat操作符的出现(在仅在Firefox中工作时,检查兼容性表),您可以编写以下一行:

var a = ['a', 'b', 'c', 'd'];
var b = ['a', 'b'];
var b1 = new Set(b);
var difference = [...new Set([...a].filter(x => !b1.has(x)))];

which will result in [ "c", "d" ].

这将导致["c", "d"]。

#13


9  

The above answer by Joshaven Potter is great. But it returns elements in array B that are not in array C, but not the other way around. For example, if var a=[1,2,3,4,5,6].diff( [3,4,5,7]); then it will output: ==> [1,2,6], but not [1,2,6,7], which is the actual difference between the two. You can still use Potter's code above but simply redo the comparison once backwards too:

以上的答案是,Joshaven Potter是伟大的。但是它返回数组B中的元素,而不是数组C中的元素,而不是相反的。例如,如果var a=[1,2,3,4,5,6]。diff([3、4、5、7]);然后它将输出:==>[1,2,6],但不是[1,2,6,7],这就是两者之间的实际差别。你仍然可以使用波特的代码,但只是简单地重新做一下比较:

Array.prototype.diff = function(a) {
    return this.filter(function(i) {return !(a.indexOf(i) > -1);});
};

////////////////////  
// Examples  
////////////////////

var a=[1,2,3,4,5,6].diff( [3,4,5,7]);
var b=[3,4,5,7].diff([1,2,3,4,5,6]);
var c=a.concat(b);
console.log(c);

This should output: [ 1, 2, 6, 7 ]

这应该输出:[1,2,6,7]

#14


8  

Another way to solve the problem

另一种解决这个问题的方法。

function diffArray(arr1, arr2) {
    return arr1.concat(arr2).filter(function (val) {
        if (!(arr1.includes(val) && arr2.includes(val)))
            return val;
    });
}

diffArray([1, 2, 3, 7], [3, 2, 1, 4, 5]);    // return [7, 4, 5]

#15


7  

Array.prototype.difference = function(e) {
    return this.filter(function(i) {return e.indexOf(i) < 0;});
};

eg:- 

[1,2,3,4,5,6,7].difference( [3,4,5] );  
 => [1, 2, 6 , 7]

#16


6  

Very Simple Solution with the filter function of JavaScript:

非常简单的解决方案,具有JavaScript的过滤功能:

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

function diffArray(arr1, arr2) {
  var newArr = [];
  var myArr = arr1.concat(arr2);
  
    newArr = myArr.filter(function(item){
      return arr2.indexOf(item) < 0 || arr1.indexOf(item) < 0;
    });
   alert(newArr);
}

diffArray(a1, a2);

#17


5  

How about this:

这个怎么样:

Array.prototype.contains = function(needle){
  for (var i=0; i<this.length; i++)
    if (this[i] == needle) return true;

  return false;
} 

Array.prototype.diff = function(compare) {
    return this.filter(function(elem) {return !compare.contains(elem);})
}

var a = new Array(1,4,7, 9);
var b = new Array(4, 8, 7);
alert(a.diff(b));

So this way you can do array1.diff(array2) to get their difference (Horrible time complexity for the algorithm though - O(array1.length x array2.length) I believe)

这样你就可以使用array1.diff(array2)来获得它们的区别(尽管算法的时间复杂度很低)(array1)。(长度)我相信。

#18


4  

Using http://phrogz.net/JS/ArraySetMath.js you can:

使用http://phrogz.net/JS/ArraySetMath.js,您可以:

var array1 = ["test1", "test2","test3", "test4"];
var array2 = ["test1", "test2","test3","test4", "test5", "test6"];

var array3 = array2.subtract( array1 );
// ["test5", "test6"]

var array4 = array1.exclusion( array2 );
// ["test5", "test6"]

#19


3  

This is working: basically merge the two arrays, look for the duplicates and push what is not duplicated into a new array which is the difference.

这是可行的:基本上合并两个数组,查找复制并将未复制的复制到一个新的数组中,这就是区别。

function diff(arr1, arr2) {
  var newArr = [];
  var arr = arr1.concat(arr2);
  
  for (var i in arr){
    var f = arr[i];
    var t = 0;
    for (j=0; j<arr.length; j++){
      if(arr[j] === f){
        t++; 
        }
    }
    if (t === 1){
      newArr.push(f);
        }
  } 
  return newArr;
}

#20


3  

function diffArray(arr1, arr2) {
  var newArr = arr1.concat(arr2);
  return newArr.filter(function(i){
    return newArr.indexOf(i) == newArr.lastIndexOf(i);
  });
}

this is works for me

这对我来说很有效。

#21


2  

Just thinking... for the sake of a challenge ;-) would this work... (for basic arrays of strings, numbers, etc.) no nested arrays

只是想…为了一个挑战;-)这项工作…(对于字符串的基本数组,数字等等)没有嵌套数组。

function diffArrays(arr1, arr2, returnUnion){
  var ret = [];
  var test = {};
  var bigArray, smallArray, key;
  if(arr1.length >= arr2.length){
    bigArray = arr1;
    smallArray = arr2;
  } else {
    bigArray = arr2;
    smallArray = arr1;
  }
  for(var i=0;i<bigArray.length;i++){
    key = bigArray[i];
    test[key] = true;
  }
  if(!returnUnion){
    //diffing
    for(var i=0;i<smallArray.length;i++){
      key = smallArray[i];
      if(!test[key]){
        test[key] = null;
      }
    }
  } else {
    //union
    for(var i=0;i<smallArray.length;i++){
      key = smallArray[i];
      if(!test[key]){
        test[key] = true;
      }
    }
  }
  for(var i in test){
    ret.push(i);
  }
  return ret;
}

array1 = "test1", "test2","test3", "test4", "test7"
array2 = "test1", "test2","test3","test4", "test5", "test6"
diffArray = diffArrays(array1, array2);
//returns ["test5","test6","test7"]

diffArray = diffArrays(array1, array2, true);
//returns ["test1", "test2","test3","test4", "test5", "test6","test7"]

Note the sorting will likely not be as noted above... but if desired, call .sort() on the array to sort it.

注意,排序可能不像上面提到的那样……但是如果需要,调用.sort()在数组上对其进行排序。

#22


2  

littlebit fix for the best answer

littlebit修复了最好的答案。

function arr_diff(a1, a2)
{
  var a=[], diff=[];
  for(var i=0;i<a1.length;i++)
    a[a1[i]]=a1[i];
  for(var i=0;i<a2.length;i++)
    if(a[a2[i]]) delete a[a2[i]];
    else a[a2[i]]=a2[i];
  for(var k in a)
   diff.push(a[k]);
  return diff;
}

this will take current type of element in consideration. b/c when we make a[a1[i]] it converts a value to string from its oroginal value, so we lost actual value.

这将考虑当前类型的元素。当我们做一个[a1[i]]时,它将一个值转换为字符串,从而失去了实际值。

#23


2  

This was inspired by the accepted answer by Thinker, but Thinker's answer seems to assume the arrays are sets. It falls apart if the arrays are [ "1", "2" ] and [ "1", "1", "2", "2" ]

这是由思想者接受的答案启发的,但思考者的答案似乎是假设数组是集合。如果数组是["1"、"2"]和["1"、"1"、"2"、"2"],它就会崩溃。

The difference between those arrays is [ "1", "2" ]. The following solution is O(n*n), so not ideal, but if you have big arrays, it has memory advantages over Thinker's solution as well.

这些数组之间的区别是["1","2"]。下面的解决方案是O(n*n),所以不理想,但是如果你有大的数组,它也比思考者的解决方案有内存优势。

If you're dealing with sets in the first place, Thinker's solution is definitely better. If you have a newer version of Javascript with access to filters, you should use those as well. This is only for those who aren't dealing with sets and are using an older version of JavaScript (for whatever reason)...

如果你首先处理的是集合,思考者的解决方案肯定更好。如果您有一个新版本的Javascript访问过滤器,您也应该使用它们。这只适用于那些不处理set和使用旧版本的JavaScript(出于某种原因)的人。

if (!Array.prototype.diff) { 
    Array.prototype.diff = function (array) {
        // if the other array is a falsy value, return a copy of this array
        if ((!array) || (!Array.prototype.isPrototypeOf(array))) { 
            return this.slice(0);
        }

        var diff = [];
        var original = this.slice(0);

        for(var i=0; i < array.length; ++i) {
            var index = original.indexOf(array[i]);
            if (index > -1) { 
                original.splice(index, 1);
            } else { 
                diff.push(array[i]);
            }
        }

        for (var i=0; i < original.length; ++i) {
            diff.push(original[i]);
        }
        return diff;
    }
}   

#24


2  

  • Pure JavaScript solution (no libraries)
  • 纯JavaScript解决方案(无库)
  • Compatible with older browsers (doesn't use filter)
  • 兼容旧的浏览器(不使用过滤器)
  • O(n^2)
  • O(n ^ 2)
  • Optional fn callback parameter that lets you specify how to compare array items
  • 可选的fn回调参数,可以指定如何比较数组项。

function diff(a, b, fn){
    var max = Math.max(a.length, b.length);
        d = [];
    fn = typeof fn === 'function' ? fn : false
    for(var i=0; i < max; i++){
        var ac = i < a.length ? a[i] : undefined
            bc = i < b.length ? b[i] : undefined;
        for(var k=0; k < max; k++){
            ac = ac === undefined || (k < b.length && (fn ? fn(ac, b[k]) : ac == b[k])) ? undefined : ac;
            bc = bc === undefined || (k < a.length && (fn ? fn(bc, a[k]) : bc == a[k])) ? undefined : bc;
            if(ac == undefined && bc == undefined) break;
        }
        ac !== undefined && d.push(ac);
        bc !== undefined && d.push(bc);
    }
    return d;
}

alert(
    "Test 1: " + 
    diff(
        [1, 2, 3, 4],
        [1, 4, 5, 6, 7]
      ).join(', ') +
    "\nTest 2: " +
    diff(
        [{id:'a',toString:function(){return this.id}},{id:'b',toString:function(){return this.id}},{id:'c',toString:function(){return this.id}},{id:'d',toString:function(){return this.id}}],
        [{id:'a',toString:function(){return this.id}},{id:'e',toString:function(){return this.id}},{id:'f',toString:function(){return this.id}},{id:'d',toString:function(){return this.id}}],
        function(a, b){ return a.id == b.id; }
    ).join(', ')
);

#25


2  

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]

#26


1  

I wanted a similar function which took in an old array and a new array and gave me an array of added items and an array of removed items, and I wanted it to be efficient (so no .contains!).

我想要一个类似的函数,它接收了一个旧数组和一个新数组,并给了我一个数组的添加项和一个移除项的数组,并且我希望它是有效的(所以没有。包含!)

You can play with my proposed solution here: http://jsbin.com/osewu3/12.

您可以在这里使用我提出的解决方案:http://jsbin.com/osewu3/12。

Can anyone see any problems/improvements to that algorithm? Thanks!

谁能看出这个算法有什么问题/改进?谢谢!

Code listing:

代码清单:

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}; 
}

#27


1  

I was looking for a simple answer that didn't involve using different libraries, and I came up with my own that I don't think has been mentioned here. I don't know how efficient it is or anything but it works;

我在寻找一个简单的答案,它不涉及使用不同的库,我提出了我自己的观点,我认为这里没有提到。我不知道它有多高效,但它能起作用;

    function find_diff(arr1, arr2) {
      diff = [];
      joined = arr1.concat(arr2);
      for( i = 0; i <= joined.length; i++ ) {
        current = joined[i];
        if( joined.indexOf(current) == joined.lastIndexOf(current) ) {
          diff.push(current);
        }
      }
      return diff;
    }

For my code I need duplicates taken out as well, but I guess that isn't always preferred.

我的代码也需要复制,但我想这并不总是可取的。

I guess the main downside is it's potentially comparing many options that have already been rejected.

我想主要的缺点是它可能会比较许多已经被拒绝的选项。

#28


1  

In response to the person who wanted to subtract one array from another...

作为对想要从另一个数组中减去一个数组的人的回应…

If no more than say 1000 elements try this...

如果不超过1000个元素尝试这个…

Setup a new variable to duplicate Array01 and call it Array03.

设置一个新的变量来复制Array01并将其命名为Array03。

Now, use the bubble sort algorithm to compare the elements of Array01 with Array02 and whenever you find a match do the following to Array03...

现在,使用气泡排序算法来比较Array01和Array02的元素,当你找到匹配的时候,可以对Array03…

 if (Array01[x]==Array02[y]) {Array03.splice(x,1);}

NB: We are modifying Array03 instead of Array01 so as not to screw up the nested loops of the bubble sort!

NB:我们正在修改Array03而不是Array01,这样就不会破坏气泡排序的嵌套循环了!

Finally, copy the contents of Array03 to Array01 with a simple assignment, and you're done.

最后,通过一个简单的任务将Array03的内容复制到Array01中,您就完成了。

#29


1  

You can use underscore.js : http://underscorejs.org/#intersection

您可以使用下划线。js:http://underscorejs.org/的十字路口

You have needed methods for array :

你需要一个数组的方法:

_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
=> [1, 3, 4]

_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2]

#30


1  

If not use hasOwnProperty then we have incorrect elements. For example:

如果不使用hasOwnProperty,那么我们就有了不正确的元素。例如:

[1,2,3].diff([1,2]); //Return ["3", "remove", "diff"] This is the wrong version

My version:

我的版本:

Array.prototype.diff = function(array2)
  {
    var a = [],
        diff = [],
        array1 = this || [];

    for (var i = 0; i < array1.length; i++) {
      a[array1[i]] = true;
    }
    for (var i = 0; i < array2.length; i++) {
      if (a[array2[i]]) {
        delete a[array2[i]];
      } else {
        a[array2[i]] = true;
      }
    }

    for (var k in a) {
      if (!a.hasOwnProperty(k)){
        continue;
      }
      diff.push(k);
    }

    return diff;
  }

#1


140  

I assume you are comparing a normal array. If not, you need to change the for loop to a for .. in loop.

我假设你在比较一个正常的数组。如果不是,则需要将for循环更改为for。在循环。

function arr_diff (a1, a2) {

    var a = [], diff = [];

    for (var i = 0; i < a1.length; i++) {
        a[a1[i]] = true;
    }

    for (var i = 0; i < a2.length; i++) {
        if (a[a2[i]]) {
            delete a[a2[i]];
        } else {
            a[a2[i]] = true;
        }
    }

    for (var k in a) {
        diff.push(k);
    }

    return diff;
}

console.log(arr_diff(['a', 'b'], ['a', 'b', 'c', 'd']));
console.log(arr_diff("abcd", "abcde"));
console.log(arr_diff("zxc", "zxc"));

A better solution, if you don't care about backward compatibility, is using filter. But still, this solution works.

如果您不关心向后兼容性,那么更好的解决方案就是使用过滤器。但是,这个解决方案仍然有效。

#2


703  

Array.prototype.diff = function(a) {
    return this.filter(function(i) {return a.indexOf(i) < 0;});
};

////////////////////  
// Examples  
////////////////////

[1,2,3,4,5,6].diff( [3,4,5] );  
// => [1, 2, 6]

["test1", "test2","test3","test4","test5","test6"].diff(["test1","test2","test3","test4"]);  
// => ["test5", "test6"]

Array.prototype.diff = function(a) {
    return this.filter(function(i) {return a.indexOf(i) < 0;});
};

////////////////////  
// Examples  
////////////////////

var dif1 = [1,2,3,4,5,6].diff( [3,4,5] );  
console.log(dif1); // => [1, 2, 6]


var dif2 = ["test1", "test2","test3","test4","test5","test6"].diff(["test1","test2","test3","test4"]);  
console.log(dif2); // => ["test5", "test6"]

Note indexOf and filter are not available in ie before ie9.

在ie9之前,注意索引和过滤器是不可用的。

#3


308  

There is a better way using ES6:

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

Intersection

十字路口

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

如何在Javascript中获得两个数组的区别?

For [1,2,3] [2,3] it will yield [2,3]. On the other hand, for [1,2,3] [2,3,5] will return the same thing.

对于[1,2,3][2,3],它将产生[2,3]。另一方面,对于[1,2,3][2,3,5]会返回相同的东西。

Difference

区别

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

如何在Javascript中获得两个数组的区别?

For [1,2,3] [2,3] it will yield [1]. On the other hand, for [1,2,3] [2,3,5] will return the same thing.

对于[1,2,3][2,3],它将产生[1]。另一方面,对于[1,2,3][2,3,5]会返回相同的东西。

For a symmetric difference, you can do:

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

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

如何在Javascript中获得两个数组的区别?

This way, you will get an array containing all the elements of arr1 that are not in arr2 and vice-versa

这样,您将得到一个包含arr1中的所有元素的数组,这些元素不在arr2中,反之亦然。

As @Joshaven Potter pointed out on his answer, you can add this to Array.prototype so it can be used like this:

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

Array.prototype.diff = arr1.filter(x => arr2.includes(x));
[1, 2, 3].diff([2, 3])

#4


285  

This is by far the easiest way to get exactly the result you are looking for, using jQuery:

这是到目前为止最简单的方法来得到您想要的结果,使用jQuery:

var diff = $(old_array).not(new_array).get();

diff now contains what was in old_array that is not in new_array

diff现在包含了在old_array中不存在于new_array中的内容。

#5


136  

The difference method in Underscore (or its drop-in replacement, Lo-Dash) can do this too:

下划线的差分方法(或它的drop-in替换,Lo-Dash)也可以这样做:

(R)eturns the values from array that are not present in the other arrays

_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
=> [1, 3, 4]

As with any Underscore function, you could also use it in a more object-oriented style:

与任何下划线函数一样,您也可以将其用于更面向对象的样式:

_([1, 2, 3, 4, 5]).difference([5, 2, 10]);

#6


57  

Plain JavaScript

There are two possible intepretations for "difference". I'll let you choose which one you want. Say you have:

有两种可能的“差异”。我会让你选择你想要的。你有说:

var a1 = ['a', 'b'     ];
var a2 = [     'b', 'c'];
  1. If you want to get ['a'], use this function:

    如果你想得到['a'],使用这个函数:

    function difference(a1, a2) {
      var result = [];
      for (var i = 0; i < a1.length; i++) {
        if (a2.indexOf(a1[i]) === -1) {
          result.push(a1[i]);
        }
      }
      return result;
    }
    
  2. If you want to get ['a', 'c'] (all elements contained in either a1 or a2, but not both -- the so-called symmetric difference), use this function:

    如果你想要得到['a', 'c'](包含在a1或a2中的所有元素,但不是两者都有,即所谓的对称差),使用这个函数:

    function symmetricDifference(a1, a2) {
      var result = [];
      for (var i = 0; i < a1.length; i++) {
        if (a2.indexOf(a1[i]) === -1) {
          result.push(a1[i]);
        }
      }
      for (i = 0; i < a2.length; i++) {
        if (a1.indexOf(a2[i]) === -1) {
          result.push(a2[i]);
        }
      }
      return result;
    }
    

Lodash / Underscore

If you are using lodash, you can use _.difference(a1, a2) (case 1 above) or _.xor(a1, a2) (case 2).

如果您使用的是lodash,您可以使用_。差异(a1, a2)(案例1)或_。xor(a1,a2)(例2)。

If you are using Underscore.js, you can use the _.difference(a1, a2) function for case 1.

如果使用下划线。js,你可以用_。不同(a1, a2)的情况1。

ES6 Set, for very large arrays

The code above works on all browsers. However, for large arrays of more than about 10,000 items, it becomes quite slow, because it has O(n²) complexity. On many modern browsers, we can take advantage of the ES6 Set object to speed things up. Lodash automatically uses Set when it's available. If you are not using lodash, use the following implementation, inspired by Axel Rauschmayer's blog post:

上面的代码适用于所有浏览器。然而,对于大型数组超过约10000件,它变得非常缓慢,因为它有O(n²)复杂性。在许多现代浏览器中,我们可以利用ES6设置对象来加快速度。Lodash在可用时自动使用Set。如果您没有使用lodash,请使用以下实现,灵感来自Axel Rauschmayer的博客文章:

function difference(a1, a2) {
  var a2Set = new Set(a2);
  return a1.filter(function(x) { return !a2Set.has(x); });
}

function symmetricDifference(a1, a2) {
  return difference(a1, a2).concat(difference(a2, a1));
}

Notes

The behavior for all examples may be surprising or non-obvious if you care about -0, +0, NaN or sparse arrays. (For most uses, this doesn't matter.)

如果您关心-0、+0、NaN或稀疏数组,那么所有示例的行为可能会令人惊讶或不明显。(在大多数情况下,这并不重要。)

#7


29  

You could use a Set in this case. It is optimized for this kind of operation (union, intersection, difference).

你可以在这个例子中使用一个集合。它对这种操作进行了优化(联合、交叉、差分)。

Make sure it applies to your case, once it allows no duplicates.

确保它适用于你的情况,一旦它不允许重复。

var a = new JS.Set([1,2,3,4,5,6,7,8,9]);
var b = new JS.Set([2,4,6,8]);

a.difference(b)
// -> Set{1,3,5,7,9}

#8


21  

function diff(a1, a2) {
  return a1.concat(a2).filter(function(val, index, arr){
    return arr.indexOf(val) === arr.lastIndexOf(val);
  });
}

Merge both the arrays, unique values will appear only once so indexOf() will be the same as lastIndexOf().

合并两个数组,唯一的值只会出现一次,所以indexOf()将与lastIndexOf()相同。

#9


17  

to subtract one array from another, simply use the snippet below:

要从另一个数组中减去一个数组,只需使用下面的代码段:

var a1 = ['1','2','3','4','6'];
var a2 = ['3','4','5'];

var items = new Array();

items = jQuery.grep(a1,function (item) {
    return jQuery.inArray(item, a2) < 0;
});

It will returns ['1,'2','6'] that are items of first array which don't exist in the second.

它将返回['1,'2','6'],这是第一个数组的项,在第二个数组中不存在。

Therefore, according to your problem sample, following code is the exact solution:

因此,根据您的问题样本,以下代码是正确的解决方案:

var array1 = ["test1", "test2","test3", "test4"];
var array2 = ["test1", "test2","test3","test4", "test5", "test6"];

var _array = new Array();

_array = jQuery.grep(array2, function (item) {
     return jQuery.inArray(item, array1) < 0;
});

#10


12  

A solution using indexOf() will be ok for small arrays but as they grow in length the performance of the algorithm approaches O(n^2). Here's a solution that will perform better for very large arrays by using objects as associative arrays to store the array entries as keys; it also eliminates duplicate entries automatically but only works with string values (or values which can be safely stored as strings):

一个使用indexOf()的解决方案对于小的数组来说是可以的,但是随着它们的长度的增长,算法的性能将接近O(n 2)。这里有一个解决方案,它将使用对象作为关联数组来将数组项存储为键,从而对非常大的数组执行得更好;它也可以自动删除重复的条目,但是只使用字符串值(或者可以安全地存储为字符串的值):

function arrayDiff(a1, a2) {
  var o1={}, o2={}, diff=[], i, len, k;
  for (i=0, len=a1.length; i<len; i++) { o1[a1[i]] = true; }
  for (i=0, len=a2.length; i<len; i++) { o2[a2[i]] = true; }
  for (k in o1) { if (!(k in o2)) { diff.push(k); } }
  for (k in o2) { if (!(k in o1)) { diff.push(k); } }
  return diff;
}

var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
arrayDiff(a1, a2); // => ['c', 'd']
arrayDiff(a2, a1); // => ['c', 'd']

#11


11  

Functional approach with ES2015

Computing the difference between two arrays is one of the Set operations. The term already indicates that the native Set type should be used, in order to increase the lookup speed. Anyway, there are three permutations when you compute the difference between two sets:

计算两个数组之间的差异是集合操作之一。这个术语已经表示应该使用本机集类型,以增加查找速度。无论如何,当你计算两组之间的差时,有三种排列:

[+left difference] [-intersection] [-right difference]
[-left difference] [-intersection] [+right difference]
[+left difference] [-intersection] [+right difference]

Here is a functional solution that reflects these permutations.

这是一个反映这些排列的功能解决方案。

Left difference:

// small, reusable auxiliary functions

const apply = f => x => f(x);
const flip = f => y => x => f(x) (y);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));


// left difference

const differencel = xs => ys => {
  const zs = createSet(ys);
  return filter(x => zs.has(x)
     ? false
     : true
  ) (xs);
};


// mock data

const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];


// run the computation

console.log( differencel(xs) (ys) );

Right difference:

differencer is trivial. It is just differencel with flipped arguments. You can write a function for convenience: const differencer = flip(differencel). That's all!

区别很简单。它只是和翻转的参数不同。您可以编写一个方便的函数:const差分= flip(不同的)。这是所有!

Symmetric difference:

Now that we have the left and right one, implementing the symmetric difference gets trivial as well:

现在我们有了左边和右边的,实现对称的差别也很简单:

// small, reusable auxiliary functions

const apply = f => x => f(x);
const flip = f => y => x => f(x) (y);
const concat = y => xs => xs.concat(y);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));


// left difference

const differencel = xs => ys => {
  const zs = createSet(ys);
  return filter(x => zs.has(x)
     ? false
     : true
  ) (xs);
};


// symmetric difference

const difference = ys => xs =>
 concat(differencel(xs) (ys)) (flip(differencel) (xs) (ys));

// mock data

const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];


// run the computation

console.log( difference(xs) (ys) );

I guess this example is a good starting point to obtain an impression what functional programming means:

我想这个例子是一个很好的起点,它可以让我们了解函数式编程的含义:

Programming with building blocks that can be plugged together in many different ways.

可以用许多不同的方式连接在一起的构建块编程。

#12


10  

With the arrival of ES6 with sets and splat operator (at the time of being works only in Firefox, check compatibility table), you can write the following one liner:

随着ES6与set和splat操作符的出现(在仅在Firefox中工作时,检查兼容性表),您可以编写以下一行:

var a = ['a', 'b', 'c', 'd'];
var b = ['a', 'b'];
var b1 = new Set(b);
var difference = [...new Set([...a].filter(x => !b1.has(x)))];

which will result in [ "c", "d" ].

这将导致["c", "d"]。

#13


9  

The above answer by Joshaven Potter is great. But it returns elements in array B that are not in array C, but not the other way around. For example, if var a=[1,2,3,4,5,6].diff( [3,4,5,7]); then it will output: ==> [1,2,6], but not [1,2,6,7], which is the actual difference between the two. You can still use Potter's code above but simply redo the comparison once backwards too:

以上的答案是,Joshaven Potter是伟大的。但是它返回数组B中的元素,而不是数组C中的元素,而不是相反的。例如,如果var a=[1,2,3,4,5,6]。diff([3、4、5、7]);然后它将输出:==>[1,2,6],但不是[1,2,6,7],这就是两者之间的实际差别。你仍然可以使用波特的代码,但只是简单地重新做一下比较:

Array.prototype.diff = function(a) {
    return this.filter(function(i) {return !(a.indexOf(i) > -1);});
};

////////////////////  
// Examples  
////////////////////

var a=[1,2,3,4,5,6].diff( [3,4,5,7]);
var b=[3,4,5,7].diff([1,2,3,4,5,6]);
var c=a.concat(b);
console.log(c);

This should output: [ 1, 2, 6, 7 ]

这应该输出:[1,2,6,7]

#14


8  

Another way to solve the problem

另一种解决这个问题的方法。

function diffArray(arr1, arr2) {
    return arr1.concat(arr2).filter(function (val) {
        if (!(arr1.includes(val) && arr2.includes(val)))
            return val;
    });
}

diffArray([1, 2, 3, 7], [3, 2, 1, 4, 5]);    // return [7, 4, 5]

#15


7  

Array.prototype.difference = function(e) {
    return this.filter(function(i) {return e.indexOf(i) < 0;});
};

eg:- 

[1,2,3,4,5,6,7].difference( [3,4,5] );  
 => [1, 2, 6 , 7]

#16


6  

Very Simple Solution with the filter function of JavaScript:

非常简单的解决方案,具有JavaScript的过滤功能:

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

function diffArray(arr1, arr2) {
  var newArr = [];
  var myArr = arr1.concat(arr2);
  
    newArr = myArr.filter(function(item){
      return arr2.indexOf(item) < 0 || arr1.indexOf(item) < 0;
    });
   alert(newArr);
}

diffArray(a1, a2);

#17


5  

How about this:

这个怎么样:

Array.prototype.contains = function(needle){
  for (var i=0; i<this.length; i++)
    if (this[i] == needle) return true;

  return false;
} 

Array.prototype.diff = function(compare) {
    return this.filter(function(elem) {return !compare.contains(elem);})
}

var a = new Array(1,4,7, 9);
var b = new Array(4, 8, 7);
alert(a.diff(b));

So this way you can do array1.diff(array2) to get their difference (Horrible time complexity for the algorithm though - O(array1.length x array2.length) I believe)

这样你就可以使用array1.diff(array2)来获得它们的区别(尽管算法的时间复杂度很低)(array1)。(长度)我相信。

#18


4  

Using http://phrogz.net/JS/ArraySetMath.js you can:

使用http://phrogz.net/JS/ArraySetMath.js,您可以:

var array1 = ["test1", "test2","test3", "test4"];
var array2 = ["test1", "test2","test3","test4", "test5", "test6"];

var array3 = array2.subtract( array1 );
// ["test5", "test6"]

var array4 = array1.exclusion( array2 );
// ["test5", "test6"]

#19


3  

This is working: basically merge the two arrays, look for the duplicates and push what is not duplicated into a new array which is the difference.

这是可行的:基本上合并两个数组,查找复制并将未复制的复制到一个新的数组中,这就是区别。

function diff(arr1, arr2) {
  var newArr = [];
  var arr = arr1.concat(arr2);
  
  for (var i in arr){
    var f = arr[i];
    var t = 0;
    for (j=0; j<arr.length; j++){
      if(arr[j] === f){
        t++; 
        }
    }
    if (t === 1){
      newArr.push(f);
        }
  } 
  return newArr;
}

#20


3  

function diffArray(arr1, arr2) {
  var newArr = arr1.concat(arr2);
  return newArr.filter(function(i){
    return newArr.indexOf(i) == newArr.lastIndexOf(i);
  });
}

this is works for me

这对我来说很有效。

#21


2  

Just thinking... for the sake of a challenge ;-) would this work... (for basic arrays of strings, numbers, etc.) no nested arrays

只是想…为了一个挑战;-)这项工作…(对于字符串的基本数组,数字等等)没有嵌套数组。

function diffArrays(arr1, arr2, returnUnion){
  var ret = [];
  var test = {};
  var bigArray, smallArray, key;
  if(arr1.length >= arr2.length){
    bigArray = arr1;
    smallArray = arr2;
  } else {
    bigArray = arr2;
    smallArray = arr1;
  }
  for(var i=0;i<bigArray.length;i++){
    key = bigArray[i];
    test[key] = true;
  }
  if(!returnUnion){
    //diffing
    for(var i=0;i<smallArray.length;i++){
      key = smallArray[i];
      if(!test[key]){
        test[key] = null;
      }
    }
  } else {
    //union
    for(var i=0;i<smallArray.length;i++){
      key = smallArray[i];
      if(!test[key]){
        test[key] = true;
      }
    }
  }
  for(var i in test){
    ret.push(i);
  }
  return ret;
}

array1 = "test1", "test2","test3", "test4", "test7"
array2 = "test1", "test2","test3","test4", "test5", "test6"
diffArray = diffArrays(array1, array2);
//returns ["test5","test6","test7"]

diffArray = diffArrays(array1, array2, true);
//returns ["test1", "test2","test3","test4", "test5", "test6","test7"]

Note the sorting will likely not be as noted above... but if desired, call .sort() on the array to sort it.

注意,排序可能不像上面提到的那样……但是如果需要,调用.sort()在数组上对其进行排序。

#22


2  

littlebit fix for the best answer

littlebit修复了最好的答案。

function arr_diff(a1, a2)
{
  var a=[], diff=[];
  for(var i=0;i<a1.length;i++)
    a[a1[i]]=a1[i];
  for(var i=0;i<a2.length;i++)
    if(a[a2[i]]) delete a[a2[i]];
    else a[a2[i]]=a2[i];
  for(var k in a)
   diff.push(a[k]);
  return diff;
}

this will take current type of element in consideration. b/c when we make a[a1[i]] it converts a value to string from its oroginal value, so we lost actual value.

这将考虑当前类型的元素。当我们做一个[a1[i]]时,它将一个值转换为字符串,从而失去了实际值。

#23


2  

This was inspired by the accepted answer by Thinker, but Thinker's answer seems to assume the arrays are sets. It falls apart if the arrays are [ "1", "2" ] and [ "1", "1", "2", "2" ]

这是由思想者接受的答案启发的,但思考者的答案似乎是假设数组是集合。如果数组是["1"、"2"]和["1"、"1"、"2"、"2"],它就会崩溃。

The difference between those arrays is [ "1", "2" ]. The following solution is O(n*n), so not ideal, but if you have big arrays, it has memory advantages over Thinker's solution as well.

这些数组之间的区别是["1","2"]。下面的解决方案是O(n*n),所以不理想,但是如果你有大的数组,它也比思考者的解决方案有内存优势。

If you're dealing with sets in the first place, Thinker's solution is definitely better. If you have a newer version of Javascript with access to filters, you should use those as well. This is only for those who aren't dealing with sets and are using an older version of JavaScript (for whatever reason)...

如果你首先处理的是集合,思考者的解决方案肯定更好。如果您有一个新版本的Javascript访问过滤器,您也应该使用它们。这只适用于那些不处理set和使用旧版本的JavaScript(出于某种原因)的人。

if (!Array.prototype.diff) { 
    Array.prototype.diff = function (array) {
        // if the other array is a falsy value, return a copy of this array
        if ((!array) || (!Array.prototype.isPrototypeOf(array))) { 
            return this.slice(0);
        }

        var diff = [];
        var original = this.slice(0);

        for(var i=0; i < array.length; ++i) {
            var index = original.indexOf(array[i]);
            if (index > -1) { 
                original.splice(index, 1);
            } else { 
                diff.push(array[i]);
            }
        }

        for (var i=0; i < original.length; ++i) {
            diff.push(original[i]);
        }
        return diff;
    }
}   

#24


2  

  • Pure JavaScript solution (no libraries)
  • 纯JavaScript解决方案(无库)
  • Compatible with older browsers (doesn't use filter)
  • 兼容旧的浏览器(不使用过滤器)
  • O(n^2)
  • O(n ^ 2)
  • Optional fn callback parameter that lets you specify how to compare array items
  • 可选的fn回调参数,可以指定如何比较数组项。

function diff(a, b, fn){
    var max = Math.max(a.length, b.length);
        d = [];
    fn = typeof fn === 'function' ? fn : false
    for(var i=0; i < max; i++){
        var ac = i < a.length ? a[i] : undefined
            bc = i < b.length ? b[i] : undefined;
        for(var k=0; k < max; k++){
            ac = ac === undefined || (k < b.length && (fn ? fn(ac, b[k]) : ac == b[k])) ? undefined : ac;
            bc = bc === undefined || (k < a.length && (fn ? fn(bc, a[k]) : bc == a[k])) ? undefined : bc;
            if(ac == undefined && bc == undefined) break;
        }
        ac !== undefined && d.push(ac);
        bc !== undefined && d.push(bc);
    }
    return d;
}

alert(
    "Test 1: " + 
    diff(
        [1, 2, 3, 4],
        [1, 4, 5, 6, 7]
      ).join(', ') +
    "\nTest 2: " +
    diff(
        [{id:'a',toString:function(){return this.id}},{id:'b',toString:function(){return this.id}},{id:'c',toString:function(){return this.id}},{id:'d',toString:function(){return this.id}}],
        [{id:'a',toString:function(){return this.id}},{id:'e',toString:function(){return this.id}},{id:'f',toString:function(){return this.id}},{id:'d',toString:function(){return this.id}}],
        function(a, b){ return a.id == b.id; }
    ).join(', ')
);

#25


2  

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]

#26


1  

I wanted a similar function which took in an old array and a new array and gave me an array of added items and an array of removed items, and I wanted it to be efficient (so no .contains!).

我想要一个类似的函数,它接收了一个旧数组和一个新数组,并给了我一个数组的添加项和一个移除项的数组,并且我希望它是有效的(所以没有。包含!)

You can play with my proposed solution here: http://jsbin.com/osewu3/12.

您可以在这里使用我提出的解决方案:http://jsbin.com/osewu3/12。

Can anyone see any problems/improvements to that algorithm? Thanks!

谁能看出这个算法有什么问题/改进?谢谢!

Code listing:

代码清单:

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}; 
}

#27


1  

I was looking for a simple answer that didn't involve using different libraries, and I came up with my own that I don't think has been mentioned here. I don't know how efficient it is or anything but it works;

我在寻找一个简单的答案,它不涉及使用不同的库,我提出了我自己的观点,我认为这里没有提到。我不知道它有多高效,但它能起作用;

    function find_diff(arr1, arr2) {
      diff = [];
      joined = arr1.concat(arr2);
      for( i = 0; i <= joined.length; i++ ) {
        current = joined[i];
        if( joined.indexOf(current) == joined.lastIndexOf(current) ) {
          diff.push(current);
        }
      }
      return diff;
    }

For my code I need duplicates taken out as well, but I guess that isn't always preferred.

我的代码也需要复制,但我想这并不总是可取的。

I guess the main downside is it's potentially comparing many options that have already been rejected.

我想主要的缺点是它可能会比较许多已经被拒绝的选项。

#28


1  

In response to the person who wanted to subtract one array from another...

作为对想要从另一个数组中减去一个数组的人的回应…

If no more than say 1000 elements try this...

如果不超过1000个元素尝试这个…

Setup a new variable to duplicate Array01 and call it Array03.

设置一个新的变量来复制Array01并将其命名为Array03。

Now, use the bubble sort algorithm to compare the elements of Array01 with Array02 and whenever you find a match do the following to Array03...

现在,使用气泡排序算法来比较Array01和Array02的元素,当你找到匹配的时候,可以对Array03…

 if (Array01[x]==Array02[y]) {Array03.splice(x,1);}

NB: We are modifying Array03 instead of Array01 so as not to screw up the nested loops of the bubble sort!

NB:我们正在修改Array03而不是Array01,这样就不会破坏气泡排序的嵌套循环了!

Finally, copy the contents of Array03 to Array01 with a simple assignment, and you're done.

最后,通过一个简单的任务将Array03的内容复制到Array01中,您就完成了。

#29


1  

You can use underscore.js : http://underscorejs.org/#intersection

您可以使用下划线。js:http://underscorejs.org/的十字路口

You have needed methods for array :

你需要一个数组的方法:

_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
=> [1, 3, 4]

_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2]

#30


1  

If not use hasOwnProperty then we have incorrect elements. For example:

如果不使用hasOwnProperty,那么我们就有了不正确的元素。例如:

[1,2,3].diff([1,2]); //Return ["3", "remove", "diff"] This is the wrong version

My version:

我的版本:

Array.prototype.diff = function(array2)
  {
    var a = [],
        diff = [],
        array1 = this || [];

    for (var i = 0; i < array1.length; i++) {
      a[array1[i]] = true;
    }
    for (var i = 0; i < array2.length; i++) {
      if (a[array2[i]]) {
        delete a[array2[i]];
      } else {
        a[array2[i]] = true;
      }
    }

    for (var k in a) {
      if (!a.hasOwnProperty(k)){
        continue;
      }
      diff.push(k);
    }

    return diff;
  }