I have two arrays with the following structures:
const array1 = [{id: 1, name: "test"}, {id: 2, name: "test2"}, {id: 3, name: "test3"}];
const array2 = [{weight: 1, ids: [1]}, {weight 3, ids: [3]}];
I want to filter array1
so that it only has items where the id does not exists within any of the ids arrays within array 2.
I tried the following:
array1.filter((item) =>
!array1?.filter((item2) =>
item2?.ids?.includes(item.id)
)
)
however it just returns an empty array.
Can anyone provide me with the correct way of doing this filtering?
CodePudding user response:
You can use array.every() to filter your array.
const array1 = [
{ id: 1, name: 'test' },
{ id: 2, name: 'test2' },
{ id: 3, name: 'test3' },
];
const array2 = [
{ weight: 1, ids: [1] },
{ weight: 3, ids: [3] },
];
const res = array1.filter((item1) =>
array2.every((item2) => !item2.ids.includes(item1.id))
);
console.log(res)
CodePudding user response:
you need to find in array2 instead of filter array1
array1.filter((item)=>
!array2.find((item2)=>item2?.ids?.includes(items.id))
)
CodePudding user response:
You can flat array2
into a single array,and then use filter on array1
const array1 = [{id: 1, name: "test"}, {id: 2, name: "test2"}, {id: 3, name: "test3"}];
const array2 = [{weight: 1, ids: [1]}, {weight:3, ids: [3]}];
let filters = array2.map(a => a.ids).flat()
let result = array1.filter(a => {
return !filters.includes(a.id)
})
console.log(result)
CodePudding user response:
filter
return a list where the callback return true and find
return a item where the callback return true
array1.filter(({id})=>{
return array2.find(({ids})=>ids.indexOf(id) == -1) == null
})
CodePudding user response:
Create a map that stores all the different ids
from array2
const array1 = [{id: 1, name: "test"}, {id: 2, name: "test2"}, {id: 3, name: "test3"}];
const array2 = [{weight: 1, ids: [2]}, {weight: 3, ids: [2]}];
const temp = array2.reduce((prev, {ids}) => {
ids.forEach(id => {
if(!prev.has(id)) {
prev.set(id, true);
}
})
return prev;
}, (new Map()));
Now filter from array1
based on the id
not present in the map
.
const ans = array1.filter(({id}) => !temp.has(id));
console.log(ans)
With map you will have better time complexity than what will be with array. (generally, add, delete, search all happen in O(1) with map)
CodePudding user response:
I think instead of a Map, the Set
might be a better aggregator for keeping the list of existing ids. Set by default make the existing Ids list unique and Set.has
method can be used to check if the id of the item from array1 exists in array2.
const existingIds = array2.reduce((list,item)=> {
list = new Set([...list, ...item.ids])
return list;
}, new Set())
array1.filter( ({id}) => !existingIds.has(id))
Benefits:
- existingIds is Set so it will have each id only once.
- Set.has a time complexity of O(1)
- Total solution will have O(n) complexity