JavaScript: 从两个数组中找出不匹配的对象

4

我有两个对象数组。

var arr1 = [{id: "145", firstname: "dave", lastname: "jones"},
            {id: "135", firstname: "mike",lastname: "williams"},
            {id: "148", firstname: "bob",lastname: "michaels"}];
var arr2 = [{id: "146", firstname: "dave", lastname: "jones"},
            {id: "135", firstname: "mike", lastname: "williams"},
            {id: "148", firstname: "bob", lastname: "michaels"}];

我希望能够找到只存在于其中一个数组中的id所对应的对象,之后将这些对象输出到控制台或者放入一个新的数组中。
因此,我希望最终能得到:
var arr1 = [{id: "145", firstname: "dave", lastname: "jones"}]
var arr2 = [{id: "146", firstname: "dave", lastname: "jones"}]

我尝试使用forEach循环并从数组中切除匹配的id

arr1.forEach(function(element1, index1) {
                let arr1Id = element1.id;
                arr2.forEach(function(element2, index2) {
                    if (arr1Id === element2.id) {
                        arr1.splice(element1, index1)
                        arr2.splice(element2, index2)

                };
            });
        });


console.log(arr1);
console.log(arr2);

但我最终得到了

arr1

[ { id: '135', firstname: 'mike', lastname: 'williams' },
  { id: '148', firstname: 'bob', lastname: 'michaels' } ]

arr2

 [ { id: '135', firstname: 'mike', lastname: 'williams' },
  { id: '148', firstname: 'bob', lastname: 'michaels' } ]

使用 Array.filter,它是专门设计用来做这种工作的。 - apple apple
我是否可以传入一个匹配两个ID的函数? - DrumBongo
目前还没有展示如何实现的答案。但是回答你的问题,不,你应该传递一个接受类型为 { id: string, firstname: string, lastname: string } 的对象并返回 true(保留)或 false(排除)的函数。 - apple apple
3个回答

6
你可以为每个数组的 id 创建一个 Set,然后通过检查存在性来筛选其他数组。

var array1 = [{ id: "145", firstname: "dave", lastname: "jones" }, { id: "135", firstname: "mike", lastname: "williams" }, { id: "148", firstname: "bob", lastname: "michaels" }],
   array2 = [{ id: "146", firstname: "dave", lastname: "jones" }, { id: "135", firstname: "mike", lastname: "williams" }, { id: "148", firstname: "bob", lastname: "michaels" }],
   set1 = new Set(array1.map(({ id }) => id)),
   set2 = new Set(array2.map(({ id }) => id)),
   result1 = array1.filter(({ id }) => !set2.has(id)),
   result2 = array2.filter(({ id }) => !set1.has(id));

console.log(result1);
console.log(result2);
.as-console-wrapper { max-height: 100% !important; top: 0; }


这似乎有点繁琐,当一个简单的 !arr.some() 就能完成工作。 - connexo
4
就大 O 表示法而言,它只有线性复杂度。 - Nina Scholz
我在谈论编码风格。我不会让那段代码通过审核。 - connexo
@NinaScholz是否保证Set的时间复杂度为O(n)?我认为它是O(nlog(n)) - apple apple
直接使用 arr.some() 也许并不是更好的选择,无论如何。 - apple apple
说到编程风格,我想使用 x=>x.id - apple apple

3

只需在Array.prototype.filter()内使用!arr.some()

const arr1 = [{id: "145", firstname: "dave", lastname: "jones"},{id: "135", firstname: "mike",lastname: "williams"},{id: "148", firstname: "bob",lastname: "michaels"}],
 arr2 = [{id: "146", firstname: "dave", lastname: "jones"},{id: "135", firstname: "mike", lastname: "williams"},{id: "148", firstname: "bob", lastname: "michaels"}],
 newArr1 = arr1.filter(x => !arr2.some(y => y.id === x.id)),
 newArr2 = arr2.filter(x => !arr1.some(y => y.id === x.id));

console.log(newArr1, newArr2);


0

Hello please try using combination of filter and findindex like the below snippet and let me know.

var arr1 = [{id: "145", firstname: "dave", lastname: "jones"},
            {id: "135", firstname: "mike",lastname: "williams"},
            {id: "148", firstname: "bob",lastname: "michaels"}];
var arr2 = [{id: "146", firstname: "dave", lastname: "jones"},
            {id: "135", firstname: "mike", lastname: "williams"},
            {id: "148", firstname: "bob", lastname: "michaels"}];
            
let unmatchedArr1 = arr1.filter(element => {
 let targetIndex = arr2.findIndex(e => element.id === e.id);
 return targetIndex >= 0 ? false : true;
})
let unmatchedArr2 = arr2.filter(element => {
 let targetIndex = arr1.findIndex(e => element.id === e.id);
 return targetIndex >= 0 ? false : true;
})

console.log(unmatchedArr1);
console.log(unmatchedArr2);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接