是否有一种方法可以在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"]
当前回答
Samuel:“对于我的代码,我也需要删除副本,但我想这并不总是可取的。 我想主要的缺点是它可能会比较许多已经被拒绝的选择。”
当比较TWO列表、数组等,且元素小于1000时,行业标准中的 3GL世界是使用冒泡排序,以避免欺骗。
代码看起来像这样……(未经测试,但应该有效)
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;
要测试输出…
for(y=0; y<Array01.length; y++) {document.write(Array01[y])}
其他回答
ES6中一个更简洁的方法是以下解决方案。
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
区别
a2.filter(d => !a1.includes(d)) // gives ["c", "d"]
十字路口
a2.filter(d => a1.includes(d)) // gives ["a", "b"]
析取联合(对称差分)
[ ...a2.filter(d => !a1.includes(d)),
...a1.filter(d => !a2.includes(d)) ]
为了获得对称差异,您需要以两种方式比较数组(或在多个数组的情况下以所有方式比较)
ES7 (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(2015年ECMAScript)
// 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)
// 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;
}
例子:
// 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"]
对象数组之间的差异
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])
);
}));
}
例子:
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}]
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) );
我想这个例子是一个很好的起点,可以让你了解函数式编程的含义:
使用可以以许多不同方式组合在一起的构建块进行编程。
类似于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' ]
// }
我想要一个类似的函数,它接受一个旧数组和一个新数组,并给我一个添加项的数组和一个删除项的数组,我希望它是有效的(所以没有.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};
}