简体   繁体   English

如何得到JavaScript中两个arrays的区别?

[英]How to get the difference between two arrays in JavaScript?

Is there a way to return the difference between two arrays in JavaScript?有没有办法返回JavaScript中两个arrays的差值?

For example:例如:

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

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

There is a better way using ES7:使用 ES7 有更好的方法:


Intersection<\/strong>路口<\/strong>

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

 Array.prototype.diff = function(a) { return this.filter(function(i) {return a.indexOf(i) < 0;}); }; \/\/\/\/\/\/\/\/\/\/\/\/\/\/ \/\/ Examples \/\/ \/\/\/\/\/\/\/\/\/\/\/\/\/\/ const dif1 = [1,2,3,4,5,6].diff( [3,4,5] ); console.log(dif1); \/\/ => [1, 2, 6] const dif2 = ["test1", "test2","test3","test4","test5","test6"].diff(["test1","test2","test3","test4"]); console.log(dif2); \/\/ => ["test5", "test6"]<\/code><\/pre>

Note<\/strong> .indexOf()<\/code> and .filter()<\/code> are not available before IE9.注意<\/strong>.indexOf()<\/code>和.filter()<\/code>在 IE9 之前不可用。

"

This answer was written in 2009, so it is a bit outdated, also it's rather educational for understanding the problem.这个答案是在 2009 年写的,所以有点过时了,对于理解这个问题也很有教育意义。 Best solution I'd use today would be我今天使用的最佳解决方案是

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

(credits to other author here) (此处归功于其他作者)

I assume you are comparing a normal array.我假设您正在比较一个普通数组。 If not, you need to change the for loop to a for .. in loop.如果没有,则需要将for循环更改为for .. in循环。

 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"));

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();

Plain JavaScript纯 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'] (包含在a1a2中的所有元素,但不能同时包含两者 - 所谓的对称差异),请使用此函数:

     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 Lodash / 下划线

If you are using lodash, you can use _.difference(a1, a2) (case 1 above) or _.xor(a1, a2) (case 2).如果您使用 lodash,您可以使用_.difference(a1, a2) (上面的案例 1)或_.xor(a1, a2) (案例 2)。

If you are using Underscore.js, you can use the _.difference(a1, a2) function for case 1.如果您使用的是 Underscore.js,则可以将_.difference(a1, a2)函数用于案例 1。

ES6 Set, for very large arrays ES6 Set,用于非常大的数组

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.然而,对于超过 10,000 个项目的大型数组,它变得相当慢,因为它具有 O(n²) 复杂度。 On many modern browsers, we can take advantage of the ES6 Set object to speed things up.在许多现代浏览器上,我们可以利用 ES6 Set对象来加快速度。 Lodash automatically uses Set when it's available. Lodash 在可用时自动使用Set If you are not using lodash, use the following implementation, inspired by Axel Rauschmayer's blog post :如果您不使用 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.如果您关心-0、+0、NaN或稀疏数组,所有示例的行为都可能令人惊讶或不明显。 (For most uses, this doesn't matter.) (对于大多数用途,这无关紧要。)

A cleaner approach in ES6 is the following solution. ES6 中一种更简洁的方法是以下解决方案。

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

To get the symmetric difference you need to compare the arrays in both ways (or in all the ways in case of multiple arrays)要获得对称差异,您需要以两种方式比较数组(或者在多个数组的情况下以所有方式)

在此处输入图像描述


ES7 (ECMAScript 2016) ES7(ECMAScript 2016)

// diff between just two arrays:
function arrayDiff(a, b) {
    return [
        ...a.filter(x => !b.includes(x)),
        ...b.filter(x => !a.includes(x))
    ];
}

// diff between multiple arrays:
function arrayDiff(...arrays) {
    return [].concat(...arrays.map( (arr, i) => {
        const others = arrays.slice(0);
        others.splice(i, 1);
        const unique = [...new Set([].concat(...others))];
        return arr.filter(x => !unique.includes(x));
    }));
}

ES6 (ECMAScript 2015) ES6(ECMAScript 2015)

// diff between just two arrays:
function arrayDiff(a, b) {
    return [
        ...a.filter(x => b.indexOf(x) === -1),
        ...b.filter(x => a.indexOf(x) === -1)
    ];
}

// diff between multiple arrays:
function arrayDiff(...arrays) {
    return [].concat(...arrays.map( (arr, i) => {
        const others = arrays.slice(0);
        others.splice(i, 1);
        const unique = [...new Set([].concat(...others))];
        return arr.filter(x => unique.indexOf(x) === -1);
    }));
}

ES5 (ECMAScript 5.1) ES5 (ECMAScript 5.1)

// diff between just two arrays:
function arrayDiff(a, b) {
    var arrays = Array.prototype.slice.call(arguments);
    var diff = [];

    arrays.forEach(function(arr, i) {
        var other = i === 1 ? a : b;
        arr.forEach(function(x) {
            if (other.indexOf(x) === -1) {
                diff.push(x);
            }
        });
    })

    return diff;
}

// diff between multiple arrays:
function arrayDiff() {
    var arrays = Array.prototype.slice.call(arguments);
    var diff = [];

    arrays.forEach(function(arr, i) {
        var others = arrays.slice(0);
        others.splice(i, 1);
        var otherValues = Array.prototype.concat.apply([], others);
        var unique = otherValues.filter(function (x, j) { 
            return otherValues.indexOf(x) === j; 
        });
        diff = diff.concat(arr.filter(x => unique.indexOf(x) === -1));
    });
    return diff;
}

Example:例子:

// diff between two arrays:
const a = ['a', 'd', 'e'];
const b = ['a', 'b', 'c', 'd'];
arrayDiff(a, b); // (3) ["e", "b", "c"]

// diff between multiple arrays
const a = ['b', 'c', 'd', 'e', 'g'];
const b = ['a', 'b'];
const c = ['a', 'e', 'f'];
arrayDiff(a, b, c); // (4) ["c", "d", "g", "f"]

Difference between Arrays of Objects对象数组之间的区别

function arrayDiffByKey(key, ...arrays) {
    return [].concat(...arrays.map( (arr, i) => {
        const others = arrays.slice(0);
        others.splice(i, 1);
        const unique = [...new Set([].concat(...others))];
        return arr.filter( x =>
            !unique.some(y => x[key] === y[key])
        );
    }));
}

Example:例子:

const a = [{k:1}, {k:2}, {k:3}];
const b = [{k:1}, {k:4}, {k:5}, {k:6}];
const c = [{k:3}, {k:5}, {k:7}];
arrayDiffByKey('k', a, b, c); // (4) [{k:2}, {k:4}, {k:6}, {k:7}]

You could use a Set in this case.在这种情况下,您可以使用Set 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}
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() 相同。

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:随着带有集合和 splat 运算符的 ES6 的到来(当时仅在 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" ]

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

Functional approach with ES2015 ES2015 的函数式方法<\/h2>

Computing the difference<\/code> between two arrays is one of the Set<\/code> operations.计算两个数组之间的difference<\/code>是Set<\/code>操作之一。 The term already indicates that the native Set<\/code> type should be used, in order to increase the lookup speed.该术语已经表明应该使用本机Set<\/code>类型,以提高查找速度。 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]<\/code><\/pre>

Here is a functional solution that reflects these permutations.这是反映这些排列的功能解决方案。

Left difference<\/code> :difference<\/code> : <\/h3>

 \/\/ 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) );<\/code><\/pre>

Right difference<\/code> :正确difference<\/code> :<\/h3>

differencer<\/code> is trivial. differencer<\/code>是微不足道的。 It is just differencel<\/code> with flipped arguments.这只是与翻转参数的differencel<\/code> 。 You can write a function for convenience: const differencer = flip(differencel)<\/code> .为方便起见,您可以编写一个函数: const differencer = flip(differencel)<\/code> 。 That's all!就这样!

Symmetric difference<\/code> :对称difference<\/code> :<\/h3>

Now that we have the left and right one, implementing the symmetric difference<\/code> gets trivial as well:现在我们有了左右一个,实现对称difference<\/code>也变得微不足道:

 \/\/ 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) );<\/code><\/pre>

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.<\/strong>使用可以以多种不同方式插入在一起的构建块进行编程。<\/strong>

"

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]

Also, you can use arrow function syntax:此外,您可以使用箭头函数语法:

const diffArray = (arr1, arr2) => arr1.concat(arr2)
    .filter(val => !(arr1.includes(val) && arr2.includes(val)));

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

A solution using indexOf()<\/code> will be ok for small arrays but as they grow in length the performance of the algorithm approaches O(n^2)<\/code> .使用indexOf()<\/code>的解决方案适用于小型数组,但随着它们的长度增长,算法的性能接近O(n^2)<\/code> 。 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):它还自动消除重复条目,但仅适用于字符串值(或可以安全存储为字符串的值):

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']

The above answer by Joshaven Potter is great. Joshaven Potter 的上述回答很棒。 But it returns elements in array B that are not in array C, but not the other way around.但它返回数组 B 中不在数组 C 中的元素,但反之则不然。 For example, if var a=[1,2,3,4,5,6].diff( [3,4,5,7]);<\/code>例如,如果var a=[1,2,3,4,5,6].diff( [3,4,5,7]);<\/code> then it will output: ==> [1,2,6]<\/code> , but not<\/strong> [1,2,6,7]<\/code> , which is the actual difference between the two.然后它将输出: ==> [1,2,6]<\/code> ,但不是<\/strong>[1,2,6,7]<\/code> ,这是两者之间的实际差异。 You can still use Potter's code above but simply redo the comparison once backwards too:您仍然可以使用上面的 Potter 代码,但也只需向后重做一次比较:

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

One Liners一班轮<\/h3>

 const unique = (a) => [...new Set(a)]; const uniqueBy = (x,f)=>Object.values(x.reduce((a,b)=>((a[f(b)]=b),a),{})); const intersection = (a, b) => a.filter((v) => b.includes(v)); const diff = (a, b) => a.filter((v) => !b.includes(v)); const symDiff = (a, b) => diff(a, b).concat(diff(b, a)); const union = (a, b) => diff(a, b).concat(b); const a = unique([1, 2, 3, 4, 5, 5]); console.log(a); const b = [4, 5, 6, 7, 8]; console.log(intersection(a, b), diff(a, b), symDiff(a, b), union(a, b)); console.log(uniqueBy( [ { id: 1, name: "abc" }, { id: 2, name: "xyz" }, { id: 1, name: "abc" }, ], (v) => v.id ));<\/code><\/pre>

"

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);<\/code><\/pre>

"

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]

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)来获得他们的差异(虽然算法的时间复杂度很可怕 - O(array1.length x array2.length) 我相信)

function diffArray(arr1, arr2) {
  var newArr = arr1.concat(arr2);
  return newArr.filter(function(i){
    return newArr.indexOf(i) == newArr.lastIndexOf(i);
  });
}
  • Pure JavaScript solution (no libraries)纯 JavaScript 解决方案(无库)<\/li>
  • Compatible with older browsers (doesn't use filter<\/code> )与旧浏览器兼容(不使用filter<\/code> )<\/li>
  • O(n^2) O(n^2)<\/li>
  • Optional fn<\/code> callback parameter that lets you specify how to compare array items可选的fn<\/code>回调参数,可让您指定如何比较数组项<\/li><\/ul>

     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(', ') );<\/code><\/pre>

    "

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"]

To find the difference of 2 arrays without duplicates:要查找没有重复的 2 个数组的差异

function difference(arr1, arr2){

  let setA = new Set(arr1);
  let differenceSet = new Set(arr2.filter(ele => !setA.has(ele)));
  return [...differenceSet ];

}

1. difference([2,2,3,4],[2,3,3,4]) will return [] 1. difference([2,2,3,4],[2,3,3,4])将返回[]

2. difference([1,2,3],[4,5,6]) will return [4,5,6] 2. difference([1,2,3],[4,5,6])将返回[4,5,6]

3. difference([1,2,3,4],[1,2]) will return [] 3. difference([1,2,3,4],[1,2])将返回[]

4. difference([1,2],[1,2,3,4]) will return [3,4] 4. difference([1,2],[1,2,3,4])将返回[3,4]

Note: The above solution requires that you always send the larger array as the second parameter.注意:上述解决方案要求您始终将较大的数组作为第二个参数发送。 To find the absolute difference, you will need to first find the larger array of the two and then work on them.要找到绝对差异,您需要首先找到两者中较大的数组,然后对它们进行处理。

To find the absolute difference of 2 arrays without duplicates:要找到 2 个没有重复的数组的绝对差异

function absDifference(arr1, arr2){

  const {larger, smaller} = arr1.length > arr2.length ? 
  {larger: arr1, smaller: arr2} : {larger: arr2, smaller: arr1}
  
  let setA = new Set(smaller);
  let absDifferenceSet = new Set(larger.filter(ele => !setA.has(ele)));
  return [...absDifferenceSet ];

}

1. absDifference([2,2,3,4],[2,3,3,4]) will return [] 1. absDifference([2,2,3,4],[2,3,3,4])将返回[]

2. absDifference([1,2,3],[4,5,6]) will return [4,5,6] 2. absDifference([1,2,3],[4,5,6])将返回[4,5,6]

3. absDifference([1,2,3,4],[1,2]) will return [3,4] 3. absDifference([1,2,3,4],[1,2])将返回[3,4]

4. absDifference([1,2],[1,2,3,4]) will return [3,4] 4. absDifference([1,2],[1,2,3,4])将返回[3,4]

Note the example 3 from both the solutions请注意两个解决方案中的示例 3

You can use underscore.js : http://underscorejs.org/#intersection您可以使用 underscore.js: http ://underscorejs.org/#intersection

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]

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; }<\/code><\/pre>

"

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!).我想要一个类似的函数,它接收一个旧数组和一个新数组,并给我一个添加项数组和一个删除项数组,我希望它高效(所以没有 .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}; 
}

\/\/es6 approach \/\/es6 方法

function diff(a, b) {
  var u = a.slice(); //dup the array
  b.map(e => {
    if (u.indexOf(e) > -1) delete u[u.indexOf(e)]
    else u.push(e)   //add non existing item to temp array
  })
  return u.filter((x) => {return (x != null)}) //flatten result
}

Symmetric<\/strong> and linear complexity<\/strong> .对称<\/strong>和线性复杂度<\/strong>。 Requires ES6.需要 ES6。

function arrDiff(arr1, arr2) {
    var arrays = [arr1, arr2].sort((a, b) => a.length - b.length);
    var smallSet = new Set(arrays[0]);

    return arrays[1].filter(x => !smallSet.has(x));
}

Use extra memory to do this.使用额外的内存来做到这一点。 That way you can solve it with less time complexity, O(n) instead of o(n*n).这样你就可以用更少的时间复杂度来解决它,O(n) 而不是 o(n*n)。

function getDiff(arr1,arr2){
let k = {};
let diff = []
arr1.map(i=>{
    if (!k.hasOwnProperty(i)) {
        k[i] = 1
    }
}
)
arr2.map(j=>{
    if (!k.hasOwnProperty(j)) {
        k[j] = 1;
    } else {
        k[j] = 2;
    }
}
)
for (var i in k) {
    if (k[i] === 1)
        diff.push(+i)
}
return diff
}
getDiff([4, 3, 52, 3, 5, 67, 9, 3],[4, 5, 6, 75, 3, 334, 5, 5, 6])

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. b / c当我们制作a [a1 [i]]时,它将其原始值转换为字符串值,因此我们丢失了实际值。

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"]
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);

This was inspired by the accepted answer by Thinker, but Thinker's answer seems to assume the arrays are sets. 这是受Thinker接受的答案启发的,但是Thinker的答案似乎是假设数组是集合。 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" ] . 这些数组之间的差是[ "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. 以下解决方案是O(n * n),所以不是理想的解决方案,但是,如果您有大数组,它也比Thinker的解决方案具有内存优势。

If you're dealing with sets in the first place, Thinker's solution is definitely better. 如果您首先要处理场景集,那么Thinker的解决方案肯定会更好。 If you have a newer version of Javascript with access to filters, you should use those as well. 如果您拥有较新版本的Javascript,并且可以访问过滤器,则也应使用这些过滤器。 This is only for those who aren't dealing with sets and are using an older version of JavaScript (for whatever reason)... 这仅适用于那些不处理集合而使用旧版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;
    }
}   

Quick solution.快速解决。 Although it seems that others have already posted different variations of the same method.尽管其他人似乎已经发布了相同方法的不同变体。 I am not sure this is the best for huge arrays, but it works for my arrays which won't be larger than 10 or 15.我不确定这是否最适合大型阵列,但它适用于我不大于 10 或 15 的阵列。

Difference b - a差异b - a

for(var i = 0; i < b.length; i++){
  for(var j = 0; j < a.length; j ++){
    var loc = b.indexOf(a[j]);
    if(loc > -1){
      b.splice(loc, 1);
    }
  }
}

Simply compares all values and returns array with the values that do not repeat. 只需比较所有值,然后返回不重复的值的数组。

var main = [9, '$', 'x', 'r', 3, 'A', '#', 0, 1];

var arr0 = ['Z', 9, 'e', '$', 'r'];
var arr1 = ['x', 'r', 3, 'A', '#'];
var arr2 = ['m', '#', 'a', 0, 'r'];
var arr3 = ['$', 1, 'n', '!', 'A'];


Array.prototype.diff = function(arrays) {
    var items = [].concat.apply(this, arguments);
    var diff = [].slice.call(items), i, l, x, pos;

    // go through all items
    for (x = 0, i = 0, l = items.length; i < l; x = 0, i++) {
        // find all positions
        while ((pos = diff.indexOf(items[i])) > -1) {
            // remove item + increase found count
            diff.splice(pos, 1) && x++;
        }
        // if item was found just once, put it back
        if (x === 1) diff.push(items[i]);
    }
    // get all not duplicated items
    return diff;
};

main.diff(arr0, arr1, arr2, arr3).join(''); // returns "Zeman!"

[].diff(main, arr0, arr1, arr2, arr3).join(''); // returns "Zeman!"
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]

If the arrays are not of simple types, then one of the above answers can be adapted: 如果数组不是简单类型,则可以采用上述答案之一:

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

This method works on arrays of complex objects. 此方法适用于复杂对象的数组。

var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
var diff = [];
for (var i in a2) {
   var found = false;
   for (var j in a1) {
      if (a2[i] === a1[j]) found = true;
   }
   if (found === false) diff.push(a2[i]);
}

That simple.就那么简单。 Could use with objects also, checking one property of object.也可以与对象一起使用,检查对象的一个​​属性。 Like,喜欢,

if (a2[i].id === a1[j].id) found = true;

Similar to Ian Grainger's solution (but in typescript):类似于 Ian Grainger 的解决方案(但在打字稿中):

function findDiffs(arrayOne: string[], arrayTwo: string[]) {

    let onlyInArrayOne = []
    let onlyInArrayTwo = []
    let share = []
    let [arrayOneCopy, arrayTwoCopy] = [[...arrayOne], [...arrayTwo]]

    arrayOneCopy.sort(); arrayTwoCopy.sort()

    while (arrayOneCopy.length !== 0 && arrayTwoCopy.length !== 0) {
        if (arrayOneCopy[0] == arrayTwoCopy[0]) {
            share.push(arrayOneCopy[0])
            arrayOneCopy.splice(0, 1)
            arrayTwoCopy.splice(0, 1)
        }
        if (arrayOneCopy[0] < arrayTwoCopy[0]) {
            onlyInArrayOne.push(arrayOneCopy[0])
            arrayOneCopy.splice(0, 1)
        }
        if (arrayOneCopy[0] > arrayTwoCopy[0]) {
            onlyInArrayTwo.push(arrayTwoCopy[0])
            arrayTwoCopy.splice(0, 1)
        }
    }
    onlyInArrayTwo = onlyInArrayTwo.concat(arrayTwoCopy)
    onlyInArrayOne = onlyInArrayOne.concat(arrayOneCopy)

    return {
        onlyInArrayOne,
        onlyInArrayTwo,
        share,
        diff: onlyInArrayOne.concat(onlyInArrayTwo)
    }
}

// arrayOne: [ 'a', 'b', 'c', 'm', 'y' ] 
// arrayTwo: [ 'c', 'b', 'f', 'h' ]
//
// Results: 
// { 
//    onlyInArrayOne: [ 'a', 'm', 'y' ],
//    onlyInArrayTwo: [ 'f', 'h' ],
//    share: [ 'b', 'c' ],
//    diff: [ 'a', 'm', 'y', 'f', 'h' ] 
// }

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"]

If not use hasOwnProperty then we have incorrect elements.如果不使用 hasOwnProperty 那么我们有不正确的元素。 For example:例如:

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

Contributing with a jQuery solution that I'm currently using:使用我目前使用的 jQuery 解决方案做出贡献:

if (!Array.prototype.diff) {
    Array.prototype.diff = function (a) {
        return $.grep(this, function (i) { return $.inArray(i, a) === -1; });
    }; 
}

CoffeeScript 版本:

diff = (val for val in array1 when val not in array2)

The selected answer is only half right.所选答案只对了一半。 You must compare the arrays both ways to get a complete answer.您必须以两种方式比较数组才能得到完整的答案。

const ids_exist = [
   '1234',
   '5678',
   'abcd',
]

const ids_new = [
  '1234',
  '5678',
  'efjk',
  '9999',
]

function __uniq_Filter (__array_1, __array_2) {
  const one_not_in_two = __array_1.filter(function (obj) {
    return __array_2.indexOf(obj) == -1
  })
  const two_not_in_one = __array_2.filter(function (obj) {
    return __array_1.indexOf(obj) == -1
  })
  return one_not_in_two.concat(two_not_in_one)
}

let uniq_filter = __uniq_Filter(ids_exist, ids_new)

console.log('uniq_filter', uniq_filter) // => [ 'abcd', 'efjk', '9999' ]

I agree with the solution of @luis-sieira我同意@luis-sieira 的解决方案

I created bit self explanatory function for beginners to understand easily step by step:我为初学者创建了一些自我解释功能,以便逐步轻松理解:

function difference(oneArr, twoArr){
  var newArr = [];
  newArr = oneArr.filter((item)=>{
      return !twoArr.includes(item)
  });
  console.log(newArr)
    let arr = twoArr.filter((item)=>{
        return !oneArr.includes(item)
     });
    newArr =  newArr.concat(arr);
  console.log(newArr)
}
difference([1, 2, 3, 5], [1, 2, 3, 4, 5])
    function arrayDiff(a, b) {
      return a.concat(b).filter(val => !(b.includes(val)));
      //(or) return a.concat(b).filter(val => !(a.includes(val) && b.includes(val)));
    }

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!注意:我们正在修改 Array03 而不是 Array01 以免搞砸冒泡排序的嵌套循环!

Finally, copy the contents of Array03 to Array01 with a simple assignment, and you're done.最后,通过简单的赋值将Array03的内容复制到Array01,大功告成。

Here is another solution which can return the differences, just like git diff: (it has been written in typescript, it you're not using typescript version, simply just remove the types)这是另一个可以返回差异的解决方案,就像 git diff :(它是用打字稿编写的,如果您没有使用打字稿版本,只需删除类型)

/**
 * util function to calculate the difference between two arrays (pay attention to 'from' and 'to'),
 * it would return the mutations from 'from' to 'to' 
 * @param { T[] } from
 * @param { T[] } to
 * @returns { { [x in string]: boolean } } it would return the stringified version of array element, true means added,
 * false means removed
 */
export function arrDiff<T>(from: T[], to: T[]): { [x in string]: boolean } {

  var diff: { [x in string]: boolean } = {};
  var newItems: T[] = []
  diff = from.reduce((a, e) => ({ ...a, [JSON.stringify(e)]: true }), {})

  for (var i = 0; i < to.length; i++) {
    if (diff[JSON.stringify(to[i])]) {
      delete diff[JSON.stringify(to[i])]
    } else {
      newItems.push(to[i])
    }
  }

  return {
    ...Object.keys(diff).reduce((a, e) => ({ ...a, [e]: false }), {}),
    ...newItems.reduce((a, e) => ({ ...a, [JSON.stringify(e)]: true }), {})
  }
}

Here is a sample of usage:下面是一个使用示例:

arrDiff(['a', 'b', 'c'], ['a', 'd', 'c', 'f']) //{"b": false, "d": true, "f": true}

Samuel: "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."塞缪尔:“对于我的代码,我也需要删除重复项,但我想这并不总是首选。我想主要的缺点是它可能会比较许多已经被拒绝的选项。”

When comparing TWO lists, Arrays, etc, and the elements are less than 1000, the industry standard in the 3GL world is to use the bubble sort which avoids dupes.当比较两个列表、数组等,并且元素小于 1000 时,3GL 世界的行业标准是使用冒泡排序,避免重复。

The code would look something like this... (untested but it should work)代码看起来像这样......(未经测试但它应该可以工作)

var Array01=new Array('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P');
var Array02=new Array('X','B','F','W','Z','X','J','P','P','O','E','N','Q');
var Array03=Array01;

for(x=1; x<Array02.length; x++) {
 for(y=0; y<Array01.length-1; y++) {
  if (Array01[y]==Array02[x]) {Array03.splice(y,1);}}}

Array01=Array03;

To test the output...要测试输出...

for(y=0; y<Array01.length; y++) {document.write(Array01[y])}

If you want to find the difference between two arrays of object you can do it like this :如果你想找到两个对象数组之间差异,你可以这样做:

 let arrObj = [{id: 1},{id: 2},{id: 3}] let arrObj2 = [{id: 1},{id: 3}] let result = arrObj.filter(x => arrObj2.every(x2 => x2.id !== x.id)) console.log(result)

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

const diffArr = a1.filter(o => !a2.includes(o));

console.log(diffArr);

Output:输出:

[ 'a', 'b' ]

There's a lot of problems with the answers I'm reading here that make them of limited value in practical programming applications.我在这里阅读的答案存在很多问题,使它们在实际编程应用程序中的价值有限。

First and foremost, you're going to want to have a way to control what it means for two items in the array to be "equal".首先,您需要有一种方法来控制数组中的两个项目“相等”意味着什么。 The === comparison is not going to cut it if you're trying to figure out whether to update an array of objects based on an ID or something like that, which frankly is probably one of the most likely scenarios in which you will want a diff function.如果您试图确定是否根据 ID 或类似的东西更新对象数组,则 === 比较不会削减它,坦率地说,这可能是您想要的最有可能的场景之一一个差异函数。 It also limits you to arrays of things that can be compared with the === operator, ie strings, ints, etc, and that's pretty much unacceptable for grown-ups.它还将您限制为可以与 === 运算符进行比较的数组,即字符串、整数等,这对于成年人来说几乎是不可接受的。

Secondly, there are three state outcomes of a diff operation:其次,diff 操作有三种状态结果:

  1. elements that are in the first array but not in the second位于第一个数组中但不在第二个数组中的元素
  2. elements that are common to both arrays两个数组共有的元素
  3. elements that are in the second array but not in the first位于第二个数组中但不在第一个数组中的元素

I think this means you need no less than 2 loops, but am open to dirty tricks if anybody knows a way to reduce it to one.我认为这意味着您需要不少于 2 个循环,但是如果有人知道将其减少到一个的方法,我会对肮脏的技巧持开放态度。

Here's something I cobbled together, and I want to stress that I ABSOLUTELY DO NOT CARE that it doesn't work in old versions of Microshaft browsers.这是我拼凑起来的东西,我想强调的是,我绝对不在乎它在旧版本的 Microshaft 浏览器中不起作用。 If you work in an inferior coding environment like IE, it's up to you to modify it to work within the unsatisfactory limitations you're stuck with.如果您在 IE 等劣质编码环境中工作,则由您来修改它以在您遇到的令人不满意的限制内工作。

Array.defaultValueComparison = function(a, b) {
    return (a === b);
};

Array.prototype.diff = function(arr, fnCompare) {

    // validate params

    if (!(arr instanceof Array))
        arr = [arr];

    fnCompare = fnCompare || Array.defaultValueComparison;

    var original = this, exists, storage, 
        result = { common: [], removed: [], inserted: [] };

    original.forEach(function(existingItem) {

        // Finds common elements and elements that 
        // do not exist in the original array

        exists = arr.some(function(newItem) {
            return fnCompare(existingItem, newItem);
        });

        storage = (exists) ? result.common : result.removed;
        storage.push(existingItem);

    });

    arr.forEach(function(newItem) {

        exists = original.some(function(existingItem) {
            return fnCompare(existingItem, newItem);
        });

        if (!exists)
            result.inserted.push(newItem);

    });

    return result;

};

This question is old but is still the top hit for javascript array subtraction so I wanted to add the solution I am using.这个问题很老,但仍然是javascript 数组减法的热门话题,所以我想添加我正在使用的解决方案。 This fits for the following case:这适用于以下情况:

var a1 = [1,2,2,3]
var a2 = [1,2]
//result = [2,3]

The following method will produced the desired result:以下方法将产生所需的结果:

function arrayDifference(minuend, subtrahend) {
  for (var i = 0; i < minuend.length; i++) {
    var j = subtrahend.indexOf(minuend[i])
    if (j != -1) {
      minuend.splice(i, 1);
      subtrahend.splice(j, 1);
    }
  }
  return minuend;
}

It should be noted that the function does not include values from the subtrahend that are not present in the minuend:应该注意的是,该函数不包括被减数中不存在的减数值:

var a1 = [1,2,3]
var a2 = [2,3,4]
//result = [1]

just trimming the string to ensure.... spaces wont affect the diff只是修剪字符串以确保......空格不会影响差异

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].trim()]) delete a[a2[i].trim()];
    else a[a2[i].trim()]=true;
    for(var k in a)
        diff.push(k);
    return diff;
}

I've tried all of these above but none worked when you needed to match without accepting duplicates.我已经尝试了以上所有这些,但是当您需要匹配而不接受重复项时,没有一个有效。

For example:例如:

var a1 = [1, 2, 1, 4], a2 = [1, 2, 4];

Would return an empty diff array because 2 would be found once in the second array, even though we need it to match twice.将返回一个空的 diff 数组,因为2将在第二个数组中找到一次,即使我们需要它匹配两次。

So I've managed to fix something up:所以我设法解决了一些问题:

Array.prototype.diff = function(a) {
    return this.filter(function(item) {
        match = a.indexOf(item);
        if (match)
            a.splice(match, 1);
        return match < 0;
    });
};

here's the function I use to get the difference between 2 arrays - It's good for numerical, string, mixed num/string arrays.这是我用来获取 2 个数组之间差异的函数 - 它适用于数值、字符串、混合 num/字符串数组。 not object literal within arrays / multidimentional arrays不是数组/多维数组中的对象字面量

function diff(arr1, arr2) {

    var x, 
        t;

    function uniq(a, b) {
        t = b;

        if( (b === 0 && x[b+1]!==a) || 
           (t > 0 && a !== x[b+1] && a !== x[b-1]) ) {
            return  a;
        }
    }


    x = arr1.concat(arr2).sort();

    return x.filter(uniq);
}

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

diff(a1, a2);

If you're array contains objects it becomes a bit more difficult if you want to compare an attribute.如果你的数组包含对象,如果你想比较一个属性会变得有点困难。

Luckily lodash makes this pretty easy using _contains and _.pluck :幸运的是lodash使用_contains_.pluck使这变得非常容易:

var list1 = [{id: 1},{id: 2}];
var list1 = [{id: 1},{id: 2}, {id: 3}];

//es6
var results = list2.filter(item => {
  return !_.contains(_.pluck(list1, 'id'), item.id);
});

//es5
var results = list2.filter(function(item){
  return !_.contains(_.pluck(list1, 'id'), item.id);
});

//results contains [{id: 3}]

Here is what I use:这是我使用的:

var newArr = a1.filter(function(elem) {
            return a2.indexOf(elem) === -1;
        }).concat( a2.filter(function(elem) {
            return a1.indexOf(elem) === -1;
        }));
console.log(newArr);

or this one或者这个

var newArr = a1.concat(a2);
        function check(item) {
            if (a1.indexOf(item) === -1 || a2.indexOf(item) === -1) {
                return item;
            }
        }
        return newArr.filter(check);
var arrayDifference = function(arr1, arr2){
  if(arr1 && arr1.length){
    if(arr2 && arr2.length > 0){
      for (var i=0, itemIndex; i<arr2.length; i++){
        itemIndex = arr1.indexOf(arr2[i]);
        if(itemIndex !== -1){
          arr1.splice(itemIndex, 1);
        }
      }
    }
    return arr1;
  }
  return [];
};

arrayDifference([1,2,3,4,5], [1,5,6]);

The hard way (in case you would like to do something more fancy than .indexOf)艰难的方式(如果你想做一些比 .indexOf 更奇特的事情)

var difference = function (source, target) {
    return source.reduce(function (diff, current) { 
        if (target.indexOf(current) === -1) { 
            diff.push(current); 
        }

        return diff; 
    }, []);
}

The easy way简单的方法

var difference = function (source, target) {
    return source.filter(function (current) {
        return target.indexOf(current) === -1;
    });
}

Data:数据:

var new_storage = JSON.parse('[{"id_order":"0003"},{"id_order":"0004"},{"id_order":"0006"}]');

var old_storage = JSON.parse('[{"id_order":"0001"},{"id_order":"0002"},{"id_order":"0003"},{"id_order":"0004"},{"id_order":"0005"}]');

using filter:使用过滤器:

var diff = new_storage
.filter(x => {if(!(old_storage.filter(y => y.id_order==x.id_order)).length){return x}})
    .concat(old_storage
    .filter(x => {if(!(new_storage.filter(y => y.id_order==x.id_order)).length){return x}})
                       ) 

console.log(JSON.stringify(diff))

result difference in two arrays两个数组的结果差异

[{"id_order":"0006"},{"id_order":"0001"},{"id_order":"0002"},{"id_order":"0005"}]
const difference = function (baseArray, arrayToCampare, callback = (a, b) => a!== b) {
  if (!(arrayToCampare instanceof Array)) {
    return baseArray;
  }
  return baseArray.filter(baseEl =>
    arrayToCampare.every(compareEl => callback(baseEl, compareEl)));
}
function array_diff(a, b) {

    let array = [];
    for(let i = 0; i <a.length; i++) {
        let k = 0;
        for( let j = 0; j < b.length; j++) {
            if(a[i]!==b[j]) {
                k++;
            }
            if(k===b.length) {
                array = array.concat(a[i]);
            }
        }

        if(b.length ===0) {
            array = array.concat(a[i]);
        }
    }
    return array;
}

Here is how I get two arrays difference.这是我如何获得两个数组差异。 Pure and clean.纯净而干净。

It will return a object that contain [add list] and [remove list].它将返回一个包含 [add list] 和 [remove list] 的对象。

  function getDiff(past, now) {
        let ret = { add: [], remove: [] };
        for (var i = 0; i < now.length; i++) {
          if (past.indexOf(now[i]) < 0)
            ret['add'].push(now[i]);
        }
        for (var i = 0; i < past.length; i++) {
          if (now.indexOf(past[i]) < 0)
            ret['remove'].push(past[i]);
        }
        return ret;
      }

You can use a common object and count the frequency of each value in the first array.您可以使用一个公共对象并计算第一个数组中每个值的频率。 For the second array, decrement the value in the common object.对于第二个数组,递减公共对象中的值。 Then iterate through all keys and add all the keys whose values is more than 1.然后遍历所有键并添加所有值大于 1 的键。

 const difference = (a1, a2) => { var obj = {}; a1.forEach(v => obj[v] = (obj[v] || 0) + 1); a2.forEach(v => obj[v] = (obj[v] || 0) - 1); return Object .keys(obj) .reduce((r,k) => { if(obj[k] > 0) r = r.concat(Array.from({length: obj[k]}).fill(k)); return r; },[]); }; const result = difference(['a', 'a', 'b', 'c', 'd'], ['a', 'b']); console.log(result);

**This returns an array of unique values, or an array of duplicates, or an array of non-duplicates (difference) for any 2 arrays based on the 'type' argument. **这将根据“类型”参数为任何 2 个数组返回唯一值数组、重复数组或非重复数组(差异)。 ** **

let json1 = ['one', 'two']
let json2 = ['one', 'two', 'three', 'four']

function uniq_n_shit (arr1, arr2, type) {

  let concat = arr1.concat(arr2)
  let set = [...new Set(concat)]

  if (!type || type === 'uniq' || type === 'unique') {

    return set

  } else if (type === 'duplicate') {

    concat = arr1.concat(arr2)
    return concat.filter(function (obj, index, self) {
      return index !== self.indexOf(obj)
    })

  } else if (type === 'not_duplicate') {

    let duplicates = concat.filter(function (obj, index, self) {
      return index !== self.indexOf(obj)
    })

    for (let r = 0; r < duplicates.length; r++) {
      let i = set.indexOf(duplicates[r]);
      if(i !== -1) {
        set.splice(i, 1);
      }
    }

    return set

  }
}

console.log(uniq_n_shit(json1, json2, null)) // => [ 'one', 'two', 'three', 'four' ]
console.log(uniq_n_shit(json1, json2, 'uniq')) // => [ 'one', 'two', 'three', 'four' ]
console.log(uniq_n_shit(json1, json2, 'duplicate')) // => [ 'one', 'two' ]
console.log(uniq_n_shit(json1, json2, 'not_duplicate')) // => [ 'three', 'four' ]

It feels easier to process this as partial functions to me.对我来说,将其作为部分功能来处理感觉更容易。 Quite surprised not to see a functional programming solution, here is mine in ES6:很惊讶没有看到函数式编程解决方案,这是我在 ES6 中的:

const arrayDiff = (a, b) => {
  return diff(b)(a);
}

const contains = (needle) => (array) => {
  for (let i=0; i < array.length; i++) {
    if (array[i] == needle) return true;
  }

  return false;
}

const diff = (compare) => {
    return (array) => array.filter((elem) => !contains(elem)(compare))
}

if you don't care about original arrays and have no problem to edit them then this is quicker algorithm:如果您不关心原始数组并且编辑它们没有问题,那么这是更快的算法:

let iterator = arrayA.values()
let result = []
for (entryA of iterator) {
    if (!arrayB.includes(entryA)) {
        result.push(entryA)
    } else {
        arrayB.splice(arrayB.indexOf(entryA), 1) 
    }
}

result.push(...arrayB)
return result

Based on Thinker's answer , but allows duplicates.基于思想者的回答,但允许重复。

The map increments map values as they appear, and decrements them if they are in the other array.地图在地图值出现时递增,如果它们在另一个数组中,则递减它们。

Any leftover will be included in the difference.任何剩余部分都将包含在差价中。

 function diff(curr, prev) { let a = curr.split('').sort(), b = prev.split('').sort(), c = arrDiff(a, b); console.log(JSON.stringify(a), '-', JSON.stringify(b), '=', JSON.stringify(c)); return c; } function arrDiff(larger, smaller) { var entries = {}; for (var i = 0; i < larger.length; i++) { entries[larger[i]] = (entries[larger[i]] || 0) + 1; } for (var i = 0; i < smaller.length; i++) { if (entries[smaller[i]]) { entries[smaller[i]] -= 1; } else { entries[smaller[i]] = (entries[smaller[i]] || 0) + 1; } } return Object.keys(entries).sort().reduce((diff, key) => { if (entries[key] > 0) { for (var i = 0; i < entries[key]; i++) { diff.push(key); } } return diff; }, []); } // Smaller is a subset of Larger console.log('Result:', JSON.stringify(diff('ENLIGHTEN', 'LENGTHEN'))); // [ I ] console.log('Result:', JSON.stringify(diff('STRENGTH', 'TENTHS'))); // [ G, R ] // Both have a unique value console.log('Result:', JSON.stringify(diff('BUBBLE', 'RUBBLE'))); // [ B, R ]
 .as-console-wrapper { top: 0; max-height: 100% !important; }

Based on previous answers... depends if you want an efficient or "nice oneliner" solution.基于以前的答案......取决于您是否想要一个有效的或“不错的oneliner”解决方案。

There are 3 approaches in general...一般有3种方法...

  • "manual iterative" (using indexOf) - naive with O(n2) complexity (slow) “手动迭代”(使用 indexOf) - O(n2) 复杂度的幼稚(慢)

     var array_diff_naive = function(a,b){ var i, la = a.length, lb = b.length, res = []; if (!la) return b; else if (!lb) return a; for (i = 0; i < la; i++) { if (b.indexOf(a[i]) === -1) res.push(a[i]); } for (i = 0; i < lb; i++) { if (a.indexOf(b[i]) === -1) res.push(b[i]); } return res; }
  • "abstract iterative" (using filter and concat library methods) - syntactic sugar for manual iterative (looks nicer, still sucks) “抽象迭代”(使用过滤器和 concat 库方法)——手动迭代的语法糖(看起来更好,但仍然很糟糕)

     var array_diff_modern = function(a1,a2){ return a1.filter(function(v) { return !a2.includes(v); } ) .concat(a2.filter(function(v) { return !a1.includes(v);})); }
  • "using hashtable" (using object keys) - much more efficient - only O(n), but has slightly limited range of input array values “使用哈希表”(使用对象键) - 效率更高 - 只有 O(n),但输入数组值的范围略有限制

     var array_diff_hash = function(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; }

See this on jsperf在 jsperf 上看到这个
https://jsperf.com/array-diff-algo https://jsperf.com/array-diff-algo

Here is a slightly modified version that uses an Object to store the hashes can handle numbers as well as strings in arrays.这是一个稍微修改过的版本,它使用一个对象来存储散列,可以处理数组中的数字和字符串。

function arrDiff(a, b) {
  const hash = {};
  a.forEach(n => { hash[n] = n; });
  b.forEach(n => {
    if (hash[n]) {
      delete hash[n];
    } else {
      hash[n] = n;
    }
  });
  return Object.values(hash);
}
var compare = array1.length > array2.length ? array1 : array2;
var compareWith = array1.length > array2.length ? array2 : array1;
var uniqueValues = compareWith.filter(function(value){
                    if(compare.indexOf(vakye) == -1)
                       return true;
                   });

This will both check which one is the larger one among the arrays and then will do the comparison.这将检查数组中哪一个较大,然后进行比较。

function diffArray(newArr, oldArr) {
    var newSet = new Set(newArr)
    var diff = []
    oldArr.forEach((a) => {
        if(!newSet.delete(a))diff.push(a)
    })
    return diff.concat(Array.from(newSet)) 
}

try it.尝试一下。

var first = [ 1, 2, 3, 4, 5 ];
    var second = [ 4, 5, 6 ];
     
    var difference = first.filter(x => second.indexOf(x) === -1);
    console.log(difference);


Output: [ 1, 2, 3]

In response to post ( Comparing two arrays containing integers JavaScript ) by adaen that was closed:响应adaen已关闭的帖子( 比较包含整数 JavaScript 的两个数组):

A couple of options:几个选项:

  1. SIMPLEST -> You can add all the entries of the second array to a hashmap.简单 -> 您可以将第二个数组的所有条目添加到哈希映射中。 Then iterate over the entries in the first array and log the ones that don't exist in the hashmap.然后迭代第一个数组中的条目并记录哈希图中不存在的条目。
const arrOne = [2,3,10,7,9,15,7,15,21,1];
const arrTwo = [3,15,1,2,21];

const hash = {};

arrTwo.forEach(a => hash[a]++);
arrOne.filter(a => typeof hash[a] === 'undefined').forEach(a => console.log(a));
  1. Your other option would be to sort both arrays.您的另一个选择是对两个数组进行排序。 Then iterate over the second array.然后迭代第二个数组。 Inside it, iterate over the first array.在其中,迭代第一个数组。 As you encounter entries in the first array that are less than the next entry in the second array but not equal to it, you log them out.当您遇到第一个数组中的条目小于第二个数组中的下一个条目但不等于它时,您将它们注销。
const arrOne = [2,3,10,7,9,15,7,15,21,1].sort((a,b)=>a-b);
const arrTwo = [3,15,1,2,21].sort((a,b)=>a-b);

var i1 = 0;
for(var i2 = 0; i2 < arrTwo.length; i2++) {
  while(arrOne[i1] < arrTwo[i2+1]) {
    if(arrOne[i1] != arrTwo[i2]) {
      console.log(arrOne[i1]);
    }
    i1++;
  }
}

If you have two list of objects如果您有两个对象列表

const people = [{name: 'cesar', age: 23}]
const morePeople = [{name: 'cesar', age: 23}, {name: 'kevin', age: 26}, {name: 'pedro', age: 25}]

let result2 = morePeople.filter(person => people.every(person2 => !person2.name.includes(person.name)))
function array_diff(array1, array2) {
   let returnArray = [];
   $.each(array1, function(index, value) {
     let findStatus = false;
     if (Array.isArray(array2)) {
       $.each(array2, function(index2, value2) {
         if (value == value2) findStatus = true;
       });
     } else {
       if (value == array2) {
         findStatus = true;
       }
     }

     if (findStatus == false) {
       returnArray.push(value);
     }
   });
   return returnArray;
}
function diffArray(arr1, arr2) {
  const newArr = [];

// arr1 match to arr2
arr1.map((item)=>{
if(arr2.indexOf(item)<0){
  console.log(item)
  newArr.push(item)
}  
})

// arr2 match to arr1
arr2.map((item)=>{
if(arr1.indexOf(item)<0){
  newArr.push(item)
}
})

  return newArr; 
}

diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]) diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5])

Output :: [ 4 ]输出 :: [ 4 ]

const dbData = [{name:'ally'}, 
{name:'James'}]
const localData = [{name:'James'}] 

const diff = dbData.filter(a =>!localData.some(b => { return a.name === b.name}))

Here is the faster approach by using map which gives o(n) complexity这是使用 map 的更快方法,它提供 o(n) 复杂度

const arr1 = ['a','b','c','d'];
const arr2 = ['a','b','c']
let table = {}
arr1.forEach(v=>{table[v]=false})
arr2.forEach(v=>{
    if(table[v]===false) table[v] = true
    else table[v] = false
})
const diff = Object.keys(table).filter(v=>table[v]==false)

I fall into this question, which was to get the difference of two simple arrays我陷入了这个问题,这是为了得到两个简单数组的差异

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

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

and I don't see why not go with the basic for loops :我不明白为什么不使用基本的 for 循环:

for(var i=0; i < a1.length; i++) {
  for(var j=0; j < a2.length; j++) {
    if(a1[i] == a2[j]) {
      a2.splice(j, 1);
    }
  }
}

which would return the needed ["c", "d"]这将返回所需的["c", "d"]

[edit] proposed right above, seen to late. [编辑] 建议在上面,看到晚了。

Anyway, any good reason to avoid this simple solution ?无论如何,有什么好的理由避免这个简单的解决方案?

转换为字符串对象类型:

[1, 1].toString() === [1, 1].toString(); // true

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM