是否有一种方法可以在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"]
当前回答
/ / 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
}
其他回答
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) );
我想这个例子是一个很好的起点,可以让你了解函数式编程的含义:
使用可以以许多不同方式组合在一起的构建块进行编程。
我想要一个类似的函数,它接受一个旧数组和一个新数组,并给我一个添加项的数组和一个删除项的数组,我希望它是有效的(所以没有.contains!)。
你可以在这里尝试我提出的解决方案:http://jsbin.com/osewu3/12。
有人能看出算法的问题或改进吗?谢谢!
代码清单:
function diff(o, n) {
// deal with empty lists
if (o == undefined) o = [];
if (n == undefined) n = [];
// sort both arrays (or this won't work)
o.sort(); n.sort();
// don't compare if either list is empty
if (o.length == 0 || n.length == 0) return {added: n, removed: o};
// declare temporary variables
var op = 0; var np = 0;
var a = []; var r = [];
// compare arrays and add to add or remove lists
while (op < o.length && np < n.length) {
if (o[op] < n[np]) {
// push to diff?
r.push(o[op]);
op++;
}
else if (o[op] > n[np]) {
// push to diff?
a.push(n[np]);
np++;
}
else {
op++;np++;
}
}
// add remaining items
if( np < n.length )
a = a.concat(n.slice(np, n.length));
if( op < o.length )
r = r.concat(o.slice(op, o.length));
return {added: a, removed: r};
}
这个怎么样:
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));
这样你就可以用array1。diff(array2)来得到它们的区别算法的时间复杂度很可怕- O(array1。长度(我相信)
对于想要从一个数组中减去另一个数组的人的回应…
如果不超过1000个元素试试这个…
设置一个新变量来复制Array01,并将其命名为Array03。
现在,使用冒泡排序算法比较Array01和Array02的元素,并在找到匹配时进行比较 对Array03执行以下操作…
if (Array01[x]==Array02[y]) {Array03.splice(x,1);}
注意:我们正在修改Array03而不是Array01,这样就不会搞砸冒泡排序的嵌套循环!
最后,用一个简单的赋值操作将Array03的内容复制到Array01,就完成了。
我在这里读到的答案有很多问题,使得它们在实际编程应用中价值有限。
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. It also limits you to arrays of things that can be compared with the === operator, i.e. strings, ints, etc, and that's pretty much unacceptable for grown-ups.
其次,diff操作有三种状态结果:
在第一个数组中但不在第二个数组中的元素 两个数组共用的元素 在第二个数组中但不在第一个数组中的元素
我认为这意味着你需要不少于2个循环,但我愿意接受肮脏的技巧,如果有人知道如何将其减少到一个。
这里是我拼凑的一些东西,我想强调的是,我绝对不在乎它在旧版本的Microshaft浏览器中不起作用。如果您在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;
};