I have a two javaScript Array
let x = [
{
id: 'Abc',
children: [
{
id: 12,
name: 'john'
}, {
id: 13,
name: 'dow'
}
]
}, {
id: 'xyz',
children: [
{
id: 123,
name: 'jack'
}, {
id: 134,
name: 'abc'
}
]
}
]
let y = [
{
id: 12,
name: 'mac'
}, {
id: 13,
name: 'dow'
}, {
id: 123,
name: 'Tom'
}, {
id: 134,
name: 'abc'
}
]
I want to update my x with y having updated array like this
[
{
id: 'Abc',
children: [
{
id: 12,
name: 'mac'
}, {
id: 13,
name: 'dow'
}
]
}, {
id: 'xyz',
children: [
{
id: 123,
name: 'Tom'
}, {
id: 134,
name: 'abc'
}
]
}
]
I tried this solution like this
x.map((a, index)=>{
a.children.map((b, i)=>{
// console.log('update')
y.find(o => o.id === b.id) || b;
})
})
but I am having undefined. I searched many answer but didn't get any luck.
x.map((a, index)=>{
a.children.map((b, i)=>{
// console.log('update')
y.find(o => o.id === b.id) || b;
})
})
First of all, you're making a common mistake while using an array function:
Brackets {} are optional for one-line instructions, but then you need to specify the return keyword.
arr.filter(v => v === 2) is equivalent to arr.filter(v => {return v === 2}). Forget return, and filter() will return an empty array.
One-line solution :
const res = x.map((a, index) => ({ ...a, children: a.children.map((b, i) => y.find(o => o.id === b.id) || b) }));
Code snippet :
let x = [
{
id: 'Abc',
children: [
{
id: 12,
name: 'john'
}, {
id: 13,
name: 'dow'
}
]
}, {
id: 'xyz',
children: [
{
id: 123,
name: 'jack'
}, {
id: 134,
name: 'abc'
}
]
}
]
let y = [
{
id: 12,
name: 'mac'
}, {
id: 13,
name: 'dow'
}, {
id: 123,
name: 'Tom'
}, {
id: 134,
name: 'abc'
}
]
const res = x.map((a, index) =>
({ ...a, children: a.children.map((b, i) => y.find(o => o.id === b.id) || b) }));
console.log(res);
First make loopup object for y, then use map for children for x
let x = [
{
id: "Abc",
children: [
{
id: 12,
name: "john",
},
{
id: 13,
name: "dow",
},
],
},
{
id: "xyz",
children: [
{
id: 123,
name: "jack",
},
{
id: 134,
name: "abc",
},
],
},
];
let y = [
{
id: 12,
name: "mac",
},
{
id: 13,
name: "dow",
},
{
id: 123,
name: "Tom",
},
{
id: 134,
name: "abc",
},
];
const lookupY = {};
y.forEach(({ id, name }) => (lookupY[id] = name));
const newX = x.map(({ id, children }) => ({
id,
children: children.map((item) => ({ id:item.id, name: lookupY[item.id] })),
}));
console.log(newX)
First of all you forgot to return the result inside callback function. Then you should not lose others keys of object.
const x = [
{
id: 'Abc',
children: [
{
id: 12,
name: 'john'
}, {
id: 13,
name: 'dow'
}
]
}, {
id: 'xyz',
children: [
{
id: 123,
name: 'jack'
}, {
id: 134,
name: 'abc'
}
]
}
];
const y = [
{
id: 12,
name: 'mac'
}, {
id: 13,
name: 'dow'
}, {
id: 123,
name: 'Tom'
}, {
id: 134,
name: 'abc'
}
];
const newArr = x.map((a, index) => {
const children = a.children.map((b, i) => {
return y.find(o => o.id === b.id) || b;
})
return { ...a, children };
})
console.log(newArr);
Related
I'm trying to find an element on a multidimentionnal array usin JAVASCRIPT function, but I get error
This is my array's data:
export const datas = [
{
id: 1,
firstName: 'John',
tables: [
{ ID: 11, title: 'Lorem' },
{ ID: 12, title: 'Ipsum' },
],
},
{
id: 2,
firstName: 'Doe',
tables: [
{
ID: 22,
title: 'Arke',
nodes: [{ name: 'Name1' }, { name: 'Name2' }, { name: 'Name3' }],
},
{ ID: 23, title: 'Korem' },
],
},
{
id: 3,
firstName: 'Brad',
tables: [
{
ID: 30,
title: 'Mern',
nodes: [{ name: 'Name4' }, { name: 'Name5' }, { name: 'Name6' }],
},
{
ID: 31,
title: 'Full',
nodes: [{ name: 'Name7' }, { name: 'Name8' }, { name: 'Name9' }],
},
],
},
];
I've tried a reccursive function but it's not work, this is my code :
export const findById = (arr, id) => {
for (let o of arr) {
if (o.tables.length > 0) {
let a = findById(o.tables.nodes, 'id');
console.log(a);
}
}
};
I want to print the Object with ID 22, the problem is that I don't have the same structure in each dimension, and it still confuse me..
My Input : 22
My output :
{
ID: 22,
title: 'Arke',
nodes: [{ name: 'Name1' }, { name: 'Name2' }, { name: 'Name3' }],
},
Have you an idea how to edit my function to get my input's response ?
Your recursive function wasn't too far off, you need to check if the item as a tables first before recursively calling it again. And then finally just check the ID in the loop.
eg..
const datas=[{id:1,firstName:"John",tables:[{ID:11,title:"Lorem"},{ID:12,title:"Ipsum"}]},{id:2,firstName:"Doe",tables:[{ID:22,title:"Arke",nodes:[{name:"Name1"},{name:"Name2"},{name:"Name3"}]},{ID:23,title:"Korem"}]},{id:3,firstName:"Brad",tables:[{ID:30,title:"Mern",nodes:[{name:"Name4"},{name:"Name5"},{name:"Name6"}]},{ID:31,title:"Full",nodes:[{name:"Name7"},{name:"Name8"},{name:"Name9"}]}]}];
function findById(arr, ID) {
for (const a of arr) {
if (a.tables) {
const r = findById(a.tables, ID);
if (r) return r;
}
if (a.ID === ID) return a;
}
}
console.log(findById(datas, 22));
if you just need the nested data you can use flatMap and find
const findById = (arr, id) =>
arr
.flatMap(d => d.tables)
.find(t => t.ID === id)
const datas = [{
id: 1,
firstName: 'John',
tables: [{
ID: 11,
title: 'Lorem'
},
{
ID: 12,
title: 'Ipsum'
},
],
},
{
id: 2,
firstName: 'Doe',
tables: [{
ID: 22,
title: 'Arke',
nodes: [{
name: 'Name1'
}, {
name: 'Name2'
}, {
name: 'Name3'
}],
},
{
ID: 23,
title: 'Korem'
},
],
},
{
id: 3,
firstName: 'Brad',
tables: [{
ID: 30,
title: 'Mern',
nodes: [{
name: 'Name4'
}, {
name: 'Name5'
}, {
name: 'Name6'
}],
},
{
ID: 31,
title: 'Full',
nodes: [{
name: 'Name7'
}, {
name: 'Name8'
}, {
name: 'Name9'
}],
},
],
},
];
console.log(findById(datas, 22))
js has amazing array options https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
the ones which will help you most are probably:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap
here are some examples
// get the base with id 22
const baseWith22ID = datas.filter(f => f.tables.filter(s => s.id = 22))
// (i guess you want this one) get all elements with id 22
const onlyElementsWith22ID = datas.flatMap(f => f.tables.filter(s => s.id = 22))
My nested json array looks like:
[
{
id: 1,
name: "Mike",
children: [
{ id: 2, name: "MikeC1" },
{ id: 3, name: "MikeC2" },
{
id: 4, name: "MikeC3",
children: [{ id: 5, name: "MikeCC1" }]
},
]
},
{
id: 6,
name: "Json",
children: [
{ id: 7, name: "JsonC1" },
{ id: 8, name: "JsonC2" },
{
id: 9, name: "JsonC3",
children: [{ id: 10, name: "JsonCC1" },{ id: 11, name: "JsonCC2" }]
},
]
}
]
Now I get a id like "11"
then get the parent ids array in json like [6,9,11]
How to do?
var id = 11
console.log(findParent(id))
//result is [6,9,11]
You need to do recursive search
const persons = [
{
id: 1,
name: "Mike",
children: [
{ id: 2, name: "MikeC1" },
{ id: 3, name: "MikeC2" },
{
id: 4, name: "MikeC3",
children: [{ id: 5, name: "MikeCC1" }]
},
]
},
{
id: 6,
name: "Json",
children: [
{ id: 7, name: "JsonC1" },
{ id: 8, name: "JsonC2" },
{
id: 9, name: "JsonC3",
children: [{ id: 10, name: "JsonCC1" },{ id: 11, name: "JsonCC2" }]
},
]
}
];
function searchRecursive(items, id) {
const allIds = [];
items.forEach(item => {
if(item.id === id) {
allIds.push(item.id);
}
else if(item.children) {
const ids = searchRecursive(item.children, id);
if(ids.length) allIds.push(item.id);
ids.forEach(id => allIds.push(id));
}
});
return allIds;
}
console.log(searchRecursive(persons, 11));
I want to keep the parent-child relationship of the tree node.
I have a JSON tree, like this
{
id: null,
children: [
{
id: 1,
children: [
{
id: 11,
children: [
{
id: 111
children: []
}
]
},
{
id: '12',
children: []
},
]
},
{
id: '2',
children: [
{
id: '21',
children: []
},
{
id: '22',
children: [
{
id: '221',
children: []
}
]
},
]
},
]
}
I want flat the tree, like this
[
{ id: 1, parent: null,},
{ id: 11, parent: 1, },
{ id: 111, parent: 11, },
{ id: 2, parent: null, },
{ id: 21, parent: 2, },
...
]
parent automatic generated
Is there any good way?
You could use flatMap method and create recursive function that will return 1D array as a result.
const data = {"id":null,"children":[{"id":1,"children":[{"id":11,"children":[{"id":111,"children":[]}]},{"id":"12","children":[]}]},{"id":"2","children":[{"id":"21","children":[]},{"id":"22","children":[{"id":"221","children":[]}]}]}]}
const flatten = (data, parent = null) =>
data.flatMap(({ id, children }) => ([
{ id, parent },
...flatten(children, id)
]))
const result = flatten(data.children);
console.log(result)
You could get the object and return an array of the flat children.
const
getFlat = ({ id, children = [] }) =>
children.flatMap(o => [{ id: o.id, parent: id }, ...getFlat(o)]);
var data = { id: null, children: [{ id: 1, children: [{ id: 11, children: [{ id: 111, children: [] }] }, { id: '12', children: [] }] }, { id: '2', children: [{ id: '21', children: [] }, { id: '22', children: [{ id: '221', children: [] }] }] }] },
flat = getFlat(data);
console.log(flat);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If compatbility with Internet Explorer is important, then the following approach which avoids the need for Array#flatMap might suit:
const input={id:null,children:[{id:'1',children:[{id:'11',children:[{id:'111',children:[]}]},{id:'12',children:[]}]},{id:'2',children:[{id:'21',children:[]},{id:'22',children:[{id:'221',children:[]}]}]}]};
const result = [];
// Define recursive function to walk through the data tree
// and produce a flat array of required data
const recurse = (item, parent) => {
// Only add item to result if it has valid id
if (item.id) {
result.push({
id: item.id,
parent: parent ? parent.id : null
});
}
// Iterate the children of this item, traversing and
// processing them in the same way
item.children.forEach(child => recurse(child, item))
}
recurse(input);
console.log(result);
You can use a simple recursion to achieve this
let data = {
id: 1,
name: 'a1',
children: [{
id: 2,
name: 'a2',
children: [{
id: 3,
name: 'b1',
children: []
},
{
id: 4,
name: 'b2',
children: []
}
]
}]
}
function flatten(data){
output = [];
return (function indentHandler(data, level, parent){
output.push({id: data['id'], parent: parent})
if (data['children'].length === 0){
return output;
}
level += 1;
data['children'].forEach(function(child){
return indentHandler(child, level, data.name);
});
return output;
})(data, 0, null);
}
flatten(data);
use recursion
var tree = {
id: null,
children: [{
id: 1,
children: [{
id: 11,
children: [{
id: 111,
children: []
}]
},
{
id: '12',
children: []
},
]
},
{
id: '2',
children: [{
id: '21',
children: []
},
{
id: '22',
children: [{
id: '221',
children: []
}]
},
]
}
]
};
var flat = [];
function flatArray(arr, parentId) {
arr.forEach(function(el) {
flat.push({
id: el.id,
parent: parentId || null
});
if (el.children)
flatArray(el.children, el.id);
});
}
flatArray(tree.children, 0)
console.log(flat);
I want to filter array of objects by another array of objects.
I have 2 array of objects like this:
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' } },
];
and I want filter array by anotherArray and return items that is not exist in anotherArray and have sub.
So my desired output is:
[ { id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } ]
Note: I've done this with for loop but it work too slow. I want to do this with using Arrays filter method
Code I have with for loop:
for (let i = 0; i < array.length; i += 1) {
let exist = false;
const item = array[i];
for (let j = 0; j < anotherArray.length; j += 1) {
const anotherItem = anotherArray[j];
if (item.id === anotherItem.id) {
exist = true;
}
}
if (item.sub && !exist) {
this.newArray.push({
text: `${item.sub.name} / ${item.name}`,
value: item.id,
});
}
}
Like Felix mentioned, Array#filter won't work faster than native for loop, however if you really want it as functional way, here's one possible solution:
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);
You can use Array.filter and then Array.some since the later would return boolean instead of the element like Array.find would:
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)
You could use JSON.stringify to compare the two objects. It would be better to write a function that compares all properties on the objects recursively.
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));
Ok, let's solve this step by step.
To simplify the process let's suppose that two elements can be considered equals if they both have the same id.
The first approach that I would use is to iterate the first array and, for each element, iterate the second one to check the conditions that you've defined above.
const A = [ /* ... */]
const B = [ /* ... */]
A.filter(el => {
let existsInB = !!B.find(e => {
return e.id === el.id
}
return existsInB && !!B.sub
})
If we are sure that the elements in A and in B are really the same when they have the same ID, we could skip all the A elements without the sub property to perform it up a little bit
A.filter(el => {
if (!el.sub) return false
let existsInB = !!B.find(e => {
return e.id === el.id
}
return existsInB
})
Now, if our arrays are bigger than that, it means that we are wasting a lot of time looking for the element into B.
Usually, in these cases, I transform the array where I look for into a map, like this
var BMap = {}
B.forEach(el => {
BMap[el.id] = el
})
A.filter(el => {
if (!el.sub) return false
return !!BMap[el.id]
})
In this way you "waste" a little bit of time to create your map at the beginning, but then you can find your elements quicker.
From here there could be even more optimizations but I think this is enought for this question
OPTIMIZED VERSION
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);
I want to filter array of objects by another array of objects.
I have 2 array of objects like this:
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' } },
];
and I want filter array by anotherArray and return items that is not exist in anotherArray and have sub.
So my desired output is:
[ { id: 3, name: 'a3', sub: { id: 8, name: 'a3 sub' } ]
Note: I've done this with for loop but it work too slow. I want to do this with using Arrays filter method
Code I have with for loop:
for (let i = 0; i < array.length; i += 1) {
let exist = false;
const item = array[i];
for (let j = 0; j < anotherArray.length; j += 1) {
const anotherItem = anotherArray[j];
if (item.id === anotherItem.id) {
exist = true;
}
}
if (item.sub && !exist) {
this.newArray.push({
text: `${item.sub.name} / ${item.name}`,
value: item.id,
});
}
}
Like Felix mentioned, Array#filter won't work faster than native for loop, however if you really want it as functional way, here's one possible solution:
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);
You can use Array.filter and then Array.some since the later would return boolean instead of the element like Array.find would:
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)
You could use JSON.stringify to compare the two objects. It would be better to write a function that compares all properties on the objects recursively.
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));
Ok, let's solve this step by step.
To simplify the process let's suppose that two elements can be considered equals if they both have the same id.
The first approach that I would use is to iterate the first array and, for each element, iterate the second one to check the conditions that you've defined above.
const A = [ /* ... */]
const B = [ /* ... */]
A.filter(el => {
let existsInB = !!B.find(e => {
return e.id === el.id
}
return existsInB && !!B.sub
})
If we are sure that the elements in A and in B are really the same when they have the same ID, we could skip all the A elements without the sub property to perform it up a little bit
A.filter(el => {
if (!el.sub) return false
let existsInB = !!B.find(e => {
return e.id === el.id
}
return existsInB
})
Now, if our arrays are bigger than that, it means that we are wasting a lot of time looking for the element into B.
Usually, in these cases, I transform the array where I look for into a map, like this
var BMap = {}
B.forEach(el => {
BMap[el.id] = el
})
A.filter(el => {
if (!el.sub) return false
return !!BMap[el.id]
})
In this way you "waste" a little bit of time to create your map at the beginning, but then you can find your elements quicker.
From here there could be even more optimizations but I think this is enought for this question
OPTIMIZED VERSION
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);