如何在javascript中对这个对象数组进行分组或合并?
我有一个例如下面的对象数组。如何在javascript中对这个对象数组进行分组或合并?
{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}
我想将它们组合起来并将其中的所有值加起来。例如,最后会是这样的:
{name: "Mc Donald", quantity: 8, maleCount: 1, femaleCount: 1}
{name: "KFC", quantity: 54, maleCount: 3, femaleCount: 3}
我该如何在JavaScript中实现这一目标?
我试图找到一些在线解决方案,但它不是我想要的。例如,这solution
您可以使用数组减少:
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);
您可以使用forEach()
循环,并加入到新阵列。您可以将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)
这样使用'this''需要更多解释。 – Bergi
你可以利用哈希表组,并使用具有可变值的按键阵列。
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; }
随着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>
是否有理由做'groups = Object.create(null)'而不是简单的'groups = {}'? –
如果你有'toString'这样的名字,你可能会得到错误的原型结果。 –
谢谢,从来没有想到这一点。 –
更多官能/通用的方法
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)
检查下面这段代码:
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);
下面是用干净的和现代的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));
我的解决方案基础上减少:
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; }
希望这将有助于
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;
});
只是注意到这个解决方案会修改一些原始对象。 – Prestaul