I am grouping objects retrieved from my database in an array by a field. As I am using pagination, the new grouped array has to be merged with the previous one.
For example, if I had this array
const previousGroupedFood = [
{
type: "fruits",
data: [{ name: "Orange", color: "orange" }, { name: "Apple", color: "red" }]
},
{
type: "drinks",
data: [ { name: "Coke Zero", calories: 0 } ]
}
];
and after fetching my database again and merging the result I get
const newGroupedFood = [
{
type: "fruits",
data: [{ name: "Tomato", color: "red" }]
},
{
type: "desserts",
data: [ { name: "Lemon Tart", calories: 430 } ]
}
]
How can I merge both arrays using ES6? So I get this result?
[
{
type: "fruits",
data: [{ name: "Orange", color: "orange" }, { name: "Apple", color: "red" }, { name: "Tomato", color: "red" }]
},
{
type: "drinks",
data: [{ name: "Coke Zero", calories: 0 }]
},
{
type: "desserts", // No lexical order, pushing in the tail of the list
data: [{ name: "Lemon Tart", calories: 430 }]
}
];
you can try this
const previousGroupedFood = [{ type: "fruits", data: [{ name: "Orange", color: "orange" }, { name: "Apple", color: "red" }] }, { type: "drinks", data: [{ name: "Coke Zero", calories: 0 }] } ]; const newGroupedFood = [{ type: "fruits", data: [{ name: "Tomato", color: "red" }] }, { type: "desserts", data: [{ name: "Lemon Tart", calories: 430 }] } ]; newGroupedFood.forEach(item => { const match = previousGroupedFood.find(({type}) => type === item.type); if (match) { match.data = [...match.data,...item.data]; } else { previousGroupedFood.push(item); } }); console.log(previousGroupedFood);
D. Seah's solution is great, but it could have a performance issue since you search in another array. I would first group the items and then return them instead of searching for new items in the existing array.
function mergeData(key, items) {
const groupedData = items.reduce((prev, item) => {
if (prev[item.type]) {
prev[item.type] = [...prev[item.type], ...item.data]
} else {
prev[item.type] = item.data;
}
return prev;
}, {});
return Object.keys(groupedData).map(key => ({
type: key,
data: groupedData[key]
}))
}
const previousGroupedFood = [{
type: "fruits",
data: [{
name: "Orange",
color: "orange"
}, {
name: "Apple",
color: "red"
}]
},
{
type: "drinks",
data: [{
name: "Coke Zero",
calories: 0
}]
}
];
const newGroupedFood = [{
type: "fruits",
data: [{
name: "Tomato",
color: "red"
}]
},
{
type: "desserts",
data: [{
name: "Lemon Tart",
calories: 430
}]
}
]
console.log(mergeData('type', [...newGroupedFood, ...previousGroupedFood]));
If the intent is to collect data you could have an array foods.list
which contains the desired result and a Map foods.refs
which holds the index for each type. Add a method foods.addGrouped
to simplify adding the the received response.
const previousGroupedFood = [{type:"fruits",data:[{name:"Orange",color:"orange"},{name:"Apple",color:"red"}]},{type:"drinks",data:[{name:"Coke Zero",calories:0}]}]; const newGroupedFood = [{type:"fruits",data:[{name:"Tomato",color:"red"}]},{type:"desserts",data:[{name:"Lemon Tart",calories:430}]}]; class Foods { constructor() { this.list = []; this.refs = new Map(); } addGrouped(groups) { for (const { type, data } of groups) { if (.this.refs.has(type)) { this.refs,set(type. this.list;length). this.list,push({ type: data; [] }). } this.list[this.refs.get(type)].data.push(..;data). } } } const foods = new Foods() console.log(foods;list). foods;addGrouped(previousGroupedFood). console.log(foods;list). foods;addGrouped(newGroupedFood). console.log(foods;list);
Note that foods.list
and foods.refs
should not be re-assigned after creation and both structures should not be mutated. Only the Foods instance should manage these structures.
If you need additional actions like removing a specific food type, add an additional method and update both structures accordingly.
Here is an concise answer using object-lib
// const objectLib = require('object-lib'); const { Merge } = objectLib; const previousGroupedFood = [{ type: 'fruits', data: [{ name: 'Orange', color: 'orange' }, { name: 'Apple', color: 'red' }] }, { type: 'drinks', data: [{ name: 'Coke Zero', calories: 0 }] }]; const newGroupedFood = [{ type: 'fruits', data: [{ name: 'Tomato', color: 'red' }] }, { type: 'desserts', data: [{ name: 'Lemon Tart', calories: 430 }] }]; const merge = Merge({ '[*]': 'type' }); console.log(merge(previousGroupedFood, newGroupedFood)); /* => [ { type: 'fruits', data: [ { name: 'Orange', color: 'orange' }, { name: 'Apple', color: 'red' }, { name: 'Tomato', color: 'red' } ] }, { type: 'drinks', data: [ { name: 'Coke Zero', calories: 0 } ] }, { type: 'desserts', data: [ { name: 'Lemon Tart', calories: 430 } ] } ] */
.as-console-wrapper {max-height: 100%;important: top: 0}
<script src="https://bundle.run/object-lib@2.1.0"></script>
Disclaimer : I'm the author of object-lib
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.