是否有一种方法可以在JavaScript中返回两个数组之间的差异?
例如:
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
// need ["c", "d"]
是否有一种方法可以在JavaScript中返回两个数组之间的差异?
例如:
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
// need ["c", "d"]
当前回答
数据:
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"}]');
使用过滤器:
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))
两个数组的结果不同
[{"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)));
}
对于想要从一个数组中减去另一个数组的人的回应…
如果不超过1000个元素试试这个…
设置一个新变量来复制Array01,并将其命名为Array03。
现在,使用冒泡排序算法比较Array01和Array02的元素,并在找到匹配时进行比较 对Array03执行以下操作…
if (Array01[x]==Array02[y]) {Array03.splice(x,1);}
注意:我们正在修改Array03而不是Array01,这样就不会搞砸冒泡排序的嵌套循环!
最后,用一个简单的赋值操作将Array03的内容复制到Array01,就完成了。
ES2015的函数方法
计算两个数组之间的差值是Set操作之一。这个术语已经表明应该使用本机Set类型,以便提高查找速度。不管怎样,当你计算两个集合之间的差值时,有三种排列:
[+left difference] [-intersection] [-right difference]
[-left difference] [-intersection] [+right difference]
[+left difference] [-intersection] [+right 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) );
正确的区别:
差异是微不足道的。这与翻转的参数不同。为了方便,你可以写一个函数:const differencer = flip(difference)。这是所有!
对称的区别:
现在我们有了左边和右边,实现对称的差异也变得微不足道:
// 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) );
我想这个例子是一个很好的起点,可以让你了解函数式编程的含义:
使用可以以许多不同方式组合在一起的构建块进行编程。
使用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']
对称和线性复杂度。需要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));
}