I am learning Java script and trying to merge an Array of objects depending on the specific properties of that object.
For example I have the following array which contains objects of properties a,b,c,pet and age. I want to create a new array with pet and age grouped if the properties a,b,c are same for 2 objects. If any of the properties in a,b,c are not matched i want to add them as a new object to my output array.
myArray = [ { a: 'animal', b: 'white', c: true, pet: 'dog1', age: 1 }, { a: 'animal', b: 'white', c: true, pet: 'dog2', age: 2 }, { a: 'animal2', b: 'white', c: true, pet: 'cat1', age: 5 }, { a: 'animal2', b: 'black', c: false, pet: 'cat2', age: 1 } ]
Output array grouped by properties a,b,c. the first element of my output array contains the combined values of objects 0,1 in input array as they have same properties of a,b,c. remaining are added as seperate values as they differ in one the properties.
outputArray = [ { a: 'animal', b: 'white', c: true, pets: [{pet:'dog1,age:1},{pet:dog2,age:2}] }, { a: 'animal2', b: 'white', c: true, pets: [{pet: 'cat1', age:5}] }, { a: 'animal2', b: 'black', c: false, pets:[{pet: 'cat2', age: 1}] } ]
Towards the end I want a array with all elements grouped by property a,b,c. Is there a efficient way to this? I tried brute forcing with for loops but it didnt work.
TIA.
Advertisement
Answer
1) You can easily achieve the result using Map
and for..of
const myArray = [ { a: "animal", b: "white", c: true, pet: "dog1", age: 1, }, { a: "animal", b: "white", c: true, pet: "dog2", age: 2, }, { a: "animal2", b: "white", c: true, pet: "cat1", age: 5, }, { a: "animal2", b: "black", c: false, pet: "cat2", age: 1, }, ]; const dict = new Map(); for (let { a, b, c, ...rest } of myArray) { const key = `${a}|${b}|${c}`; !dict.has(key) ? dict.set(key, { a, b, c, pets: [{ ...rest }] }) : dict.get(key).pets.push(rest); } const result = [...dict.values()]; console.log(result);
/* This is not a part of answer. It is just to give the output full height. So IGNORE IT */ .as-console-wrapper { max-height: 100% !important; top: 0;
2) You can also achieve the samer result using Object.values
and reduce
const myArray = [ { a: "animal", b: "white", c: true, pet: "dog1", age: 1, }, { a: "animal", b: "white", c: true, pet: "dog2", age: 2, }, { a: "animal2", b: "white", c: true, pet: "cat1", age: 5, }, { a: "animal2", b: "black", c: false, pet: "cat2", age: 1, }, ]; const result = Object.values( myArray.reduce((dict, { a, b, c, ...rest }) => { const key = `${a}|${b}|${c}`; !dict[key] ? (dict[key] = { a, b, c, pets: [{ ...rest }] }) : dict[key].pets.push(rest); return dict; }, {}) ); console.log(result);
/* This is not a part of answer. It is just to give the output full height. So IGNORE IT */ .as-console-wrapper { max-height: 100% !important; top: 0;