我想用另一个对象数组过滤对象数组。
我有2个这样的对象数组:
<div id="list">
</div>
,我想用const array = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } },
{ id: 4, name: 'a4', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
const anotherArray = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
过滤array
并返回在anotherArray中不存在且具有sub的项。
所以我想要的输出是:
anotherArray
注意:我已经使用for循环完成了此操作,但是它工作太慢。我想通过使用数组过滤器方法来做到这一点
我使用for循环的代码:
[ { id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } ]
答案 0 :(得分:2)
您可以先使用Array.filter
,然后再使用Array.some
,因为后者将返回布尔值,而不是像Array.find
这样的元素:
const a1 = [ { id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } }, { id: 2, name: 'a2', sub: null }, { id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } }, { id: 4, name: 'a4', sub: null }, { id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } }, ];
const a2 = [ { id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } }, { id: 2, name: 'a2', sub: null }, { id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } }, ];
const result = a1.filter(({id, sub}) => !a2.some(x => x.id == id) && sub)
console.log(result)
答案 1 :(得分:1)
好的,让我们逐步解决这个问题。
为简化该过程,我们假设两个元素如果具有相同的id
,则可以认为是相等的。
我将使用的第一种方法是迭代第一个数组,并针对每个元素迭代第二个数组以检查您在上面定义的条件。
const A = [ /* ... */]
const B = [ /* ... */]
A.filter(el => {
let existsInB = !!B.find(e => {
return e.id === el.id
}
return existsInB && !!B.sub
})
如果我们确定A和B中的元素具有相同的ID时,它们确实是相同的,那么我们可以跳过没有sub
属性的所有A元素来对其执行一点操作>
A.filter(el => {
if (!el.sub) return false
let existsInB = !!B.find(e => {
return e.id === el.id
}
return existsInB
})
现在,如果我们的数组大于该数组,则意味着我们正在浪费大量时间在B中寻找元素。 通常,在这种情况下,我将要查找的数组转换为地图,就像这样
var BMap = {}
B.forEach(el => {
BMap[el.id] = el
})
A.filter(el => {
if (!el.sub) return false
return !!BMap[el.id]
})
通过这种方式,您一开始就“浪费”了一点时间来创建地图,但是随后您可以更快地找到元素。
从这里可能会有更多的优化,但是我认为这足以解决这个问题
答案 2 :(得分:0)
就像Felix提到的那样,Array#filter
的运行速度不会比原生for循环快,但是,如果您真的希望将其作为功能性方式,则可以采用以下一种解决方案:
const array = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } },
{ id: 4, name: 'a4', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
const anotherArray = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
const r = array.filter((elem) => !anotherArray.find(({ id }) => elem.id === id) && elem.sub);
console.log(r);
答案 3 :(得分:0)
您可以使用JSON.stringify比较两个对象。最好编写一个函数来递归比较对象上的所有属性。
const array = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } },
{ id: 4, name: 'a4', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
const anotherArray = [
{ id: 1, name: 'a1', sub: { id: 6, name: 'a1 sub' } },
{ id: 2, name: 'a2', sub: null },
{ id: 5, name: 'a5', sub: { id: 10, name: 'a5 sub' } },
];
const notIn = (array1, array2) => array1.filter(item1 => {
const item1Str = JSON.stringify(item1);
return !array2.find(item2 => item1Str === JSON.stringify(item2))
}
);
console.log(notIn(array, anotherArray));
答案 4 :(得分:0)
const array = [{
id: 1,
name: "a1",
sub: {
id: 6,
name: "a1 sub"
}
},
{
id: 2,
name: "a2",
sub: null
},
{
id: 3,
name: "a3",
sub: {
id: 8,
name: "a3 sub"
}
},
{
id: 4,
name: "a4",
sub: null
},
{
id: 5,
name: "a5",
sub: {
id: 10,
name: "a5 sub"
}
},
];
const anotherArray = [{
id: 1,
name: "a1",
sub: {
id: 6,
name: "a1 sub"
}
},
{
id: 2,
name: "a2",
sub: null
},
{
id: 5,
name: "a5",
sub: {
id: 10,
name: "a5 sub"
}
},
];
const dict = anotherArray.reduce((acc, curr) => {
const { id } = curr;
acc[id] = curr;
return acc;
}, {});
const result = array.filter((obj) => {
const search = dict[obj.id];
if (!search && obj.sub) return true;
return false;
});
console.log(result);