我有两个数组 list1
和 list2
,它们的对象具有某些属性; userId
是 Id 或唯一属性:
list1 = [
{ userId: 1234, userName: 'XYZ' },
{ userId: 1235, userName: 'ABC' },
{ userId: 1236, userName: 'IJKL' },
{ userId: 1237, userName: 'WXYZ' },
{ userId: 1238, userName: 'LMNO' }
]
list2 = [
{ userId: 1235, userName: 'ABC' },
{ userId: 1236, userName: 'IJKL' },
{ userId: 1252, userName: 'AAAA' }
]
我正在寻找一种简单的方法来执行以下三个操作:
list1操作list2
应该返回元素的交集:[ { userId: 1235, userName: 'ABC' }, { userId: 1236, userName: 'IJKL' } ]
list1 operation list2
应该返回list1
中没有出现在list2
中的所有元素的列表:[ { userId: 1234, userName: 'XYZ' }, { userId: 1237, userName: 'WXYZ' }, { userId: 1238, userName: 'LMNO' } ]
list2 操作 list1
应该返回list2
中没有出现在list1
中的元素列表:[ { userId: 1252, userName: 'AAAA' } ]
最佳答案
您可以定义三个函数 inBoth
、inFirstOnly
和 inSecondOnly
,它们都将两个列表作为参数,并尽可能返回一个列表从函数名来理解。主要逻辑可以放在一个共同的函数 operation
中,这三个函数都依赖。
这里有一些可供选择的操作
的实现,您可以在下面找到一个片段:
- 普通的旧 JavaScript
for
循环 - 使用
filter
和一些
数组方法的箭头函数 - 使用
Set
优化查找
普通的 for
循环
// Generic helper function that can be used for the three operations:
function operation(list1, list2, isUnion) {
var result = [];
for (var i = 0; i < list1.length; i++) {
var item1 = list1[i],
found = false;
for (var j = 0; j < list2.length && !found; j++) {
found = item1.userId === list2[j].userId;
}
if (found === !!isUnion) { // isUnion is coerced to boolean
result.push(item1);
}
}
return result;
}
// Following functions are to be used:
function inBoth(list1, list2) {
return operation(list1, list2, true);
}
function inFirstOnly(list1, list2) {
return operation(list1, list2);
}
function inSecondOnly(list1, list2) {
return inFirstOnly(list2, list1);
}
// Sample data
var list1 = [
{ userId: 1234, userName: 'XYZ' },
{ userId: 1235, userName: 'ABC' },
{ userId: 1236, userName: 'IJKL' },
{ userId: 1237, userName: 'WXYZ' },
{ userId: 1238, userName: 'LMNO' }
];
var list2 = [
{ userId: 1235, userName: 'ABC' },
{ userId: 1236, userName: 'IJKL' },
{ userId: 1252, userName: 'AAAA' }
];
console.log('inBoth:', inBoth(list1, list2));
console.log('inFirstOnly:', inFirstOnly(list1, list2));
console.log('inSecondOnly:', inSecondOnly(list1, list2));
使用filter
和一些
数组方法的箭头函数
这使用了一些 ES5 和 ES6 特性:
// Generic helper function that can be used for the three operations:
const operation = (list1, list2, isUnion = false) =>
list1.filter( a => isUnion === list2.some( b => a.userId === b.userId ) );
// Following functions are to be used:
const inBoth = (list1, list2) => operation(list1, list2, true),
inFirstOnly = operation,
inSecondOnly = (list1, list2) => inFirstOnly(list2, list1);
// Sample data
const list1 = [
{ userId: 1234, userName: 'XYZ' },
{ userId: 1235, userName: 'ABC' },
{ userId: 1236, userName: 'IJKL' },
{ userId: 1237, userName: 'WXYZ' },
{ userId: 1238, userName: 'LMNO' }
];
const list2 = [
{ userId: 1235, userName: 'ABC' },
{ userId: 1236, userName: 'IJKL' },
{ userId: 1252, userName: 'AAAA' }
];
console.log('inBoth:', inBoth(list1, list2));
console.log('inFirstOnly:', inFirstOnly(list1, list2));
console.log('inSecondOnly:', inSecondOnly(list1, list2));
优化查找
由于嵌套循环,上述解决方案的时间复杂度为 O(n²) -- some
也表示循环。因此,对于大型数组,您最好在用户 ID 上创建一个(临时)散列。这可以通过提供 Set
(ES6) 作为将生成过滤器回调函数的函数的参数来即时完成。然后该函数可以使用 has
在恒定时间内执行查找:
// Generic helper function that can be used for the three operations:
const operation = (list1, list2, isUnion = false) =>
list1.filter(
(set => a => isUnion === set.has(a.userId))(new Set(list2.map(b => b.userId)))
);
// Following functions are to be used:
const inBoth = (list1, list2) => operation(list1, list2, true),
inFirstOnly = operation,
inSecondOnly = (list1, list2) => inFirstOnly(list2, list1);
// Sample data
const list1 = [
{ userId: 1234, userName: 'XYZ' },
{ userId: 1235, userName: 'ABC' },
{ userId: 1236, userName: 'IJKL' },
{ userId: 1237, userName: 'WXYZ' },
{ userId: 1238, userName: 'LMNO' }
];
const list2 = [
{ userId: 1235, userName: 'ABC' },
{ userId: 1236, userName: 'IJKL' },
{ userId: 1252, userName: 'AAAA' }
];
console.log('inBoth:', inBoth(list1, list2));
console.log('inFirstOnly:', inFirstOnly(list1, list2));
console.log('inSecondOnly:', inSecondOnly(list1, list2));
关于javascript - 两个包含对象的数组的差分和交集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33356504/