Reputation: 97
I have this array of objects:
const arrayOfObjects = [{
id: 10,
children: [1000]
},
{
id: 10,
children: [2000]
},
{
id: 20,
children: [1000]
},
{
id: 20,
children: [1000, 2000]
},
{
id: 20,
children: [2000]
},
];
I want to remove duplicates using this code:
const arrayHashMap = arrayOfObjects.reduce((obj, item) => {
if (obj[item.id]) {
// obj[item.id].children.push(...item.children);
const temporaryArray = [...obj[item.id].children, ...item.children];
obj[item.id].children = [...new Set(temporaryArray)];
} else {
obj[item.id] = {
...item
};
}
return obj;
}, {});
const result = Object.values(arrayHashMap);
In this code I commented part where I push values to array. I tried to use "new Set" to remove duplicates from final array, but I am always assigning the value to "obj[item.id].children". Is this OK or is there a better way to write this?
Expected result:
[{
id: 10,
children: [1000, 2000]
}, {
id: 20,
children: [1000, 2000]
}]
Thanks
Upvotes: 0
Views: 832
Reputation: 718
i dont know about "better", but perhaps terser:
const arrayOfObjects = [{
id: 10,
children: [1000]
},
{
id: 10,
children: [2000]
},
{
id: 20,
children: [1000]
},
{
id: 20,
children: [1000, 2000]
},
{
id: 20,
children: [2000]
},
];
const arrayHashmap = arrayOfObjects.reduce((obj, {
id,
children
}) => ({
...obj,
[id]: {
id,
children: [...new Set([
...obj[id]?.children ?? [],
...children
])]
}
}), {})
const result = Object.values(arrayHashmap);
console.log(result)
edit: whoops, the "tidy" button changed semantics. fixed.
Upvotes: 0
Reputation: 1099
You can also achieve expected output by running the below code
makeMapping = {};
for (let obj of arrayOfObjects) {
makeMapping[obj.id] = {...obj, children: [...new Set([...obj.children, ...(makeMapping[obj.id]?.children || [])])]};
}
console.log(Object.values(makeMapping));
Upvotes: 0
Reputation: 391
you can temporary transform data structure to more simple
const objectOfArray = {}; your id is key, your children is value
I use name initialData for refer to your array
const objectOfArray = {};
initialData.forEach(e => {
if (objectOfArray[e.id] {
objectOfArray[e.id].push(...e.children);
} else {
objectOfArray[e.id] = [...e.children];
}
});
const result = Object.entries(objectOfArray).map(([id, children]) => {
return {
id,
children: children.filter((e, i) => i === chilren.indexOf(i)),
}
});
Upvotes: 0
Reputation: 1
you can try this fiddle : https://jsfiddle.net/d0kboywv/2/
const arrayOfObjects = [
{
id: 10,
children: [1000]
},
{
id: 10,
children: [2000]
},
{
id: 20,
children: [1000]
},
{
id: 20,
children: [1000, 2000, 3000]
},
{
id: 20,
children: [2000, 4000]
},
];
let mappedArray = new Map(arrayOfObjects.map(o => [o.id, {}] ));
for (let obj of arrayOfObjects) {
let child = mappedArray.get(obj.id);
for (let [key, val] of Object.entries(obj.children)) {
child[key] = (child[key] || new Set).add(val);
}
}
let result = Array.from(mappedArray.entries(), ([id, child]) => ({
id,
children: [...new Set(Object.entries(child).map(([k, v]) =>
[...v]
).reduce((a, b) => a.concat(b), []))].sort()
}));
console.log(result);
It do the job for me !
Upvotes: 0
Reputation: 3910
const arr = [
{
id: 10,
children: [1000],
},
{
id: 10,
children: [2000],
},
{
id: 20,
children: [1000],
},
{
id: 20,
children: [1000, 2000],
},
{
id: 20,
children: [2000],
},
];
let result = arr.reduce((acc, i) => {
let obj = acc.find((a) => a.id === i.id);
obj ? (obj.children = [...new Set(obj.children.concat(i.children))]): acc.push(i);
return acc;
}, []);
console.log(result);
Upvotes: 0
Reputation: 386604
You could group by id
and check the array if the value not exists, then push the value.
const
data = [{ id: 10, children: [1000] }, { id: 10, children: [2000] }, { id: 20, children: [1000] }, { id: 20, children: [1000, 2000] }, { id: 20, children: [2000] }],
result = Object.values(data.reduce((r, { id, children }) => {
r[id] ??= { id, children: [] };
children.forEach(v => {
if (!r[id].children.includes(v)) r[id].children.push(v);
})
return r;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 5853
Use Array#prototype#reduce
to reduce over the array and initialize a set over the children property and keep on adding to the set and lastly map the set back to an array.
const arrayOfObjects = [{
id: 10,
children: [1000]
},
{
id: 10,
children: [2000]
},
{
id: 20,
children: [1000]
},
{
id: 20,
children: [1000, 2000]
},
{
id: 20,
children: [2000]
},
];
const result = Object.values(
arrayOfObjects.reduce((r, c) => {
r[c.id] = r[c.id] || {
id: c.id,
children: new Set()
};
c.children.forEach((item) => r[c.id].children.add(item));
return r;
}, Object.create(null))
)
.map((x) => ({
id: x.id,
children: [...x.children]
}));
console.log(result);
Upvotes: 0