简体   繁体   English

如何在javascript中分组或合并此对象数组?

[英]How to group or merge this array of objects in javascript?

I have an array of objects like below for example. 我有一个像下面这样的对象数组。

{name: "Mc Donald", quantity: 4, maleCount: 1, femaleCount: 0}
{name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0}
{name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0}
{name: "Mc Donald", quantity: 4, maleCount: 0, femaleCount: 1}
{name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1}
{name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0}
{name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1}
{name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1}

I want to group them up and adding up all the values in it. 我想将它们分组并加总其中的所有值。 For example, the final would be like this: 例如,最终将是这样的:

{name: "Mc Donald", quantity: 8, maleCount: 1, femaleCount: 1}
{name: "KFC", quantity: 54, maleCount: 3, femaleCount: 3}

How can I achieve this in JavaScript? 如何在JavaScript中实现?

I have tried to find some solution online but it is not the one I wanted. 我试图在网上找到一些解决方案,但这不是我想要的。 For example this solution 例如这个解决方案

You can use array reduce: 您可以使用数组减少:

 var arr = [ {name: "Mc Donald", quantity: 4, maleCount: 1, femaleCount: 0}, {name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0}, {name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0}, {name: "Mc Donald", quantity: 4, maleCount: 0, femaleCount: 1}, {name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1}, {name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0}, {name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1}, {name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1} ]; var finalArr = arr.reduce((m, o) => { var found = m.find(p => p.name === o.name); if (found) { found.quantity += o.quantity; found.maleCount += o.maleCount; found.femaleCount += o.femaleCount; } else { m.push(o); } return m; }, []); console.log(finalArr); 

You can use forEach() loop and add to new array. 您可以使用forEach()循环并添加到新数组。 You can pass empty object as thisArg parameter that you can use as this in your callback function and in second forEach context of this will still be the same as in first callback function because of arrow function. 您可以将空对象作为thisArg参数传递,并可以在回调函数中使用this ,并且在第二个forEach上下文中,由于箭头函数, this仍将与第一个回调函数相同。

 var data = [{"name":"Mc Donald","quantity":4,"maleCount":1,"femaleCount":0},{"name":"KFC","quantity":9,"maleCount":1,"femaleCount":0},{"name":"KFC","quantity":9,"maleCount":1,"femaleCount":0},{"name":"Mc Donald","quantity":4,"maleCount":0,"femaleCount":1},{"name":"KFC","quantity":9,"maleCount":0,"femaleCount":1},{"name":"KFC","quantity":9,"maleCount":1,"femaleCount":0},{"name":"KFC","quantity":9,"maleCount":0,"femaleCount":1},{"name":"KFC","quantity":9,"maleCount":0,"femaleCount":1}] var result = [], keys = ['quantity', 'maleCount', 'femaleCount'] data.forEach(function(e) { if(!this[e.name]) result.push(this[e.name] = e); else keys.forEach(k => this[e.name][k] += e[k]) }, {}) console.log(result) 

You could group with a hash table and use an array for the keys with variable values. 您可以与哈希表进行分组,并为具有可变值的键使用数组。

 var array = [{ name: "Mc Donald", quantity: 4, maleCount: 1, femaleCount: 0 }, { name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0 }, { name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0 }, { name: "Mc Donald", quantity: 4, maleCount: 0, femaleCount: 1 }, { name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1 }, { name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0 }, { name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1 }, { name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1 }], groups = Object.create(null), result = array.reduce(function (r, o) { var values = ['quantity', 'maleCount', 'femaleCount']; if (!groups[o.name]) { groups[o.name] = { name: o.name }; r.push(groups[o.name]); values.forEach(function (k) { groups[o.name][k] = 0; }); } values.forEach(function (k) { groups[o.name][k] += o[k]; }); return r; }, []); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

With linq.js 使用linq.js

 var array = [{ name: "Mc Donald", quantity: 4, maleCount: 1, femaleCount: 0 }, { name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0 }, { name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0 }, { name: "Mc Donald", quantity: 4, maleCount: 0, femaleCount: 1 }, { name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1 }, { name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0 }, { name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1 }, { name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1 }], result = Enumerable.From(array) .GroupBy( "$.name", null, "{ name: $.Key, quantity: $$.Sum('$.quantity'), maleCount: $$.Sum('$.maleCount'), femaleCount: $$.Sum('$.femaleCount') }" ) .ToArray(); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.js"></script> 

My solution based on reduce: 我的解决方案基于reduce:

 let data = [ {name: "Mc Donald", quantity: 4, maleCount: 1, femaleCount: 0}, {name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0}, {name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0}, {name: "Mc Donald", quantity: 4, maleCount: 0, femaleCount: 1}, {name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1}, {name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0}, {name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1}, {name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1} ]; // We will only keep an array of values of the merged object let result = Object.values( // Merge data to name indexed objects data.reduce((p,c) => { // Ensure key (name) exists if (!p[c.name]) { // If first occurence, duplicate object (to avoid modification of original array) p[c.name] = Object.assign({}, c); } else { // If key (name) already exists, sum up relevant attributes p[c.name].quantity += c.quantity; p[c.name].maleCount += c.maleCount; p[c.name].femaleCount += c.femaleCount; } // return updated object return p; }, {}) ); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

hope this will help 希望这会有所帮助

More functional/universal approach 更多功能/通用方法

 const normalizeValue = (value) => value === undefined ? 0 : value const sumUpProps = (props = []) => (a = {}, b = {}) => { const result = {} props.forEach((prop) => { result[prop] = normalizeValue(a[prop]) + normalizeValue(b[prop]) }) return result } const data = [ {name: "Mc Donald", quantity: 4, maleCount: 1, femaleCount: 0}, {name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0}, {name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0}, {name: "Mc Donald", quantity: 4, maleCount: 0, femaleCount: 1}, {name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1}, {name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0}, {name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1}, {name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1} ] const entries = {} const sumObjects = sumUpProps(['quantity', 'maleCount', 'femaleCount']) data.forEach((item) => { const entry = entries[item.name] || {} entries[item.name] = sumObjects(entry, item) }) console.log(entries) 

check this code below: 检查以下代码:

var array = [
    {name: "Mc Donald", quantity: 4, maleCount: 1, femaleCount: 0},
    {name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0},
    {name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0},
    {name: "Mc Donald", quantity: 4, maleCount: 0, femaleCount: 1},
    {name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1},
    {name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0},
    {name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1},
    {name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1},
];

var result = [];

for(var index in array){
    var obj = array[index];
    if(result.hasOwnProperty(obj.name)) {
        result[obj.name].quantity += obj.quantity;
        result[obj.name].maleCount += obj.maleCount;
        result[obj.name].femaleCount += obj.femaleCount;
    }else{
        result[obj.name] = {};
        result[obj.name].quantity = obj.quantity;
        result[obj.name].maleCount = obj.maleCount;
        result[obj.name].femaleCount = obj.femaleCount;
    }
}

console.log(result);

Here is a generic solution that uses clean and modern JavaScript: 这是使用干净现代JavaScript的通用解决方案:

 function groupRestaurants(restaurants) { const groups = new Map(); restaurants.forEach(restaurant => { const group = findOrCreateGroup(groups, restaurant.name); addRestaurantToGroup(group, restaurant); }); return [...groups.values()]; } function findOrCreateGroup(groups, name) { let group = groups.get(name); if (!group) { group = { name }; groups.set(name, group); } return group; } function addRestaurantToGroup(group, restaurant) { for (const [key, value] of Object.entries(restaurant)) { if (key !== 'name') { if (group.hasOwnProperty(key)) { group[key] += value; } else { group[key] = value; } } } } const restaurants = [ { name: "Mc Donald", quantity: 4, maleCount: 1, femaleCount: 0 }, { name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0 }, { name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0 }, { name: "Mc Donald", quantity: 4, maleCount: 0, femaleCount: 1 }, { name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1 }, { name: "KFC", quantity: 9, maleCount: 1, femaleCount: 0 }, { name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1 }, { name: "KFC", quantity: 9, maleCount: 0, femaleCount: 1 } ]; console.log(groupRestaurants(restaurants)); 

Lodash makes your life easy. Lodash使您的生活变得轻松。

_.map(_.groupBy(yourArrayHere, 'name'), (groupMembers, groupKey) => {
    let sumObject = {name: groupKey};

    _.forEach(['quantity', 'maleCount', 'femaleCount'], (property) => {
        sumObject[property] = 0;
        _.forEach(groupMembers, (member) => {
            sumObject[property] += member[property];
        });
    });

    return sumObject;
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM