I have such a case:
const ids = {
// id: parentId
"2": "1",
"3": "1"
}
const input = [
{
id: "1",
data: [1],
},
{
id: "2",
data: [2]
},
{
id: "3",
data: [3]
},
{
id: "4",
data: [4]
}
]
const output = [
{
id: "1",
data: [1,2,3]
},
{
id: "4",
data: [4]
}
]
With this ids I wanted to create some kind of config, which will determine which object in input array should have merged data (if there is no id-parentId pair defined, it should stay as it is). I belive code above is better explanation than this story. I tried with some mappings but without any nice result. This 'ids' array is an example, maybe there is a better way to define it so it will simplify the case? What do you think? I will be grateful for any hint
CodePudding user response:
You can use reduce()
. Create the output first as an object that uses id
as the key. You can convert it to an array at the end with Object.values()
.
const ids = {
// id: parentId
"2": "1",
"3": "1"
}
const input = [{
id: "1",
data: [1],
},
{
id: "2",
data: [2]
},
{
id: "3",
data: [3]
},
{
id: "4",
data: [4]
}
]
const output = Object.values(input.reduce((acc, {
id,
data
}) => {
if (id in ids) { // replace id with parent
id = ids[id];
}
if (id in acc) {
acc[id].data = acc[id].data.concat(data);
} else {
acc[id] = {
id,
data};
}
return acc;
}, {}));
console.log(output);
CodePudding user response:
You could take the references for same groups.
const
ids = { 2: "1", 3: "1" },
input = [{ id: "1", data: [1] }, { id: "2", data: [2] }, { id: "3", data: [3] }, { id: "4", data: [4] }],
output = Object.values(input.reduce((r, { id, data }) => {
id = ids[id] ?? id;
(r[id] ??= { id, data: [] }).data.push(...data);
return r;
}, {}));
console.log(output);
.as-console-wrapper { max-height: 100% !important; top: 0; }
CodePudding user response:
You can try to cycle the input and modifying it in place, something like this should work:
const input = [
{
id: '1',
data: [1]
},
{
id: '2',
data: [2]
},
{
id: '3',
data: [3]
},
{
id: '4',
data: [4]
}
]
const config = {
2: '1',
3: '1'
}
const merge = ({ input, config } = {}) => {
for (const [childId, parentId] of Object.entries(config)) {
const childIndex = input.findIndex(i => i.id == childId)
const parent = input.find(i => i.id == parentId)
parent.data.push(...input[childIndex].data)
input.splice(childIndex, 1)
}
return input
}
console.log(merge({ input, config }))
CodePudding user response:
you could do it like this:
let ids = { 2: "1", 3: "1" }
let input = [{ id: "1", data: [1] }, { id: "2", data: [2] }, { id: "3", data: [3] }, { id: "4", data: [4] }];
let keys = Object.keys(ids);
let objs = input.slice();//in order to not mutate the source input
const output = objs.map(currObj=>{
let currId = currObj.id;
if(keys.includes(currId)){
let changeObj = objs.find(obj=>obj.id==ids[currId])
changeObj.data.push(...currObj.data)
}
return currObj
})
console.log(output);
NOTE: I used slice() in order to not mutate the source input
CodePudding user response:
You can use Array#reduce
, Object.entries
and Array#map
methods as follows:
const ids = { "2": "1", "3": "1" },
input = [ { id: "1", data: [1], }, { id: "2", data: [2] }, { id: "3", data: [3] }, { id: "4", data: [4] } ],
output = Object.entries(
input.reduce(
(acc,{id,data}) =>
ids[id] ?
({...acc,[ids[id]]:[...(acc[ids[id]] || []),...data]}) :
({...acc,[id]:[...(acc[id] || []), ...data]}),{}
)
)
.map(([id,data]) => ({id,data}));
console.log( output );
//OUTPUT: [{"id":"1","data":[1,2,3]},{"id":"4","data":[4]}]