Суммировать все данные в массиве объектов в новый массив объектов
У меня есть массив объектов, который выглядит так:
var data = [{costOfAirtickets: 2500, costOfHotel: 1200},{costOfAirtickets: 1500, costOfHotel: 1000}]
и я хочу суммировать каждый элемент массива, чтобы создать такой массив:
var result = [{costOfAirtickets: 4000, costOfHotel: 3200}]
Я использовал карту и уменьшил функцию, но мне удалось суммировать отдельный элемент следующим образом:
data.map(item => ite.costOfAirtickets).reduce((prev, next)=>prev + next); // 22
На данный момент это дает единственное значение, которое не то, что я хочу, по первому объяснению.
Есть ли способ сделать это в Javascript или, возможно, с lodash.
Ответы
Ответ 1
Использование for..in
для итерации объекта и reduce
до итерации массива
var data = [{costOfAirtickets: 2500, costOfHotel: 1200},{costOfAirtickets: 1500, costOfHotel: 1000}];
var result = [data.reduce((acc, n) => {
for (var prop in n) {
if (acc.hasOwnProperty(prop)) acc[prop] += n[prop];
else acc[prop] = n[prop];
}
return acc;
}, {})]
console.log(result)
Ответ 2
Используйте Lodash для упрощения вашей жизни.
const _ = require('lodash')
let keys = ['costOfAirtickets', 'costOfHotel'];
let results = _.zipObject(keys, keys.map(key => _.sum( _.map(data, key))))
...
{ costOfAirtickets: 4000, costOfHotel: 2200 }
Объяснение:
-
_.sum(_.map(data, key))
: генерирует сумму каждого массива -
_.zipObject
: _.zipObject
результаты с суммой массива - используя
keys.map()
для суммы каждого ключа, поскольку _.map
не гарантирует порядок.
Документация:
Ответ 3
Чтобы создать результирующее/уменьшенное значение, вы должны использовать .reduce()
вместо .map()
:
let data = [
{costOfAirtickets: 2500, costOfHotel: 1200},
{costOfAirtickets: 1500, costOfHotel: 1000}
];
let result = data.reduce(
(a, c) => (Object.keys(c).forEach(k => (a[k] = (a[k] || 0) + c[k])), a), {}
);
console.log(result);
Ответ 4
Вам не нужно отображать массив, вы действительно просто уменьшаете его.
const totalCostOfAirTickets: data.reduce((prev, next) => prev + next.costOfAirTickets, 0)
const totalCostOfHotel: data.reduce((prev, next) => prev + next.costOfHotel, 0)
const totals = [{totalCostOfAirTickets, totalCostOfHotel}]
За один проход вы можете сделать что-то вроде
const totals = data.reduce((prev, next) => {
prev.costOfAirTickets += next.costOfAirTickets;
prev.costOfHotel += next.costOfHotel;
}, {costOfAirTickets: 0, costOfHotel: 0})
Ответ 5
Вот подход lodash
_(data).flatMap(_.entries).groupBy(0).mapValues(v=>_.sumBy(v, 1)).value()
Он будет суммировать все уникальные ключи.
var data = [{costOfAirtickets: 2500, costOfHotel: 1200},{costOfAirtickets: 1500, costOfHotel: 1000}];
var res = _(data).flatMap(_.entries).groupBy(0).mapValues(v=>_.sumBy(v, 0)).value();
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Ответ 6
Другим решением было бы использовать Map
(не Array.prototype.map), поскольку он имеет несколько заметных отличий по сравнению с объектами:
var data = [{
costOfAirtickets: 2500,
costOfHotel: 1200
}, {
costOfAirtickets: 1500,
costOfHotel: 1000
}]
let sums = data.reduce((collection,rcd)=>{
Object.entries(rcd).forEach(([key,value])=>{
let sum = collection.get(key) || 0
collection.set(key, sum + +value)
})
return collection
}, new Map())
console.log(...sums.entries())
Ответ 7
Вы можете использовать простой цикл forEach()
для этого:
var data = [{costOfAirtickets: 2500, costOfHotel: 1200},{costOfAirtickets: 1500, costOfHotel: 1000}];
var res = [];
var tempObj = {};
data.forEach(({costOfAirtickets, costOfHotel}) => {
tempObj['costOfAirtickets'] = (tempObj['costOfAirtickets'] || 0) + costOfAirtickets;
tempObj['costOfHotel'] = (tempObj['costOfHotel'] || 0) + costOfHotel;
});
res.push(tempObj);
console.log(res);
Ответ 8
Попробуйте использовать сокращение только как в приведенном ниже фрагменте. Попробуйте избежать нескольких итераций. Надеюсь, что нижеприведенный фрагмент поможет!
var data = [{costOfAirtickets: 2500, costOfHotel: 1200},{costOfAirtickets: 1500, costOfHotel: 1000}]
var total = data.reduce(function (result,value,key) {
result['costOfAirtickets'] = result['costOfAirtickets'] + value['costOfAirtickets'];
result['costOfHotel'] = result['costOfHotel'] + value['costOfHotel'];
return result},{costOfAirtickets:0,costOfHotel:0});
console.log(total)
Ответ 9
Вы можете уменьшить массив, взяв объект для суммирования.
var data = [{ costOfAirtickets: 2500, costOfHotel: 1200 }, { costOfAirtickets: 1500, costOfHotel: 1000 }],
keys = ['costOfAirtickets', 'costOfHotel'],
sum = data.reduce((r, o) => {
keys.forEach(k => r[k] += o[k]);
return r;
}, Object.assign(...keys.map(k => ({ [k]: 0 }))));
console.log(sum);
Ответ 10
map
объект и вычислить сумму и сохранить ее в другом.
var data = [{costOfAirtickets: 2500, costOfHotel: 1200},{costOfAirtickets: 1500, costOfHotel: 1000}];
var result = [];
var sum = 0;
var costsum = 0;
data.map(function(item, key){
var cost = item;
//nsole.log(cost);
sum = sum + cost.costOfAirtickets;
costsum = costsum + cost.costOfHotel;
});
result = [{costOfAirtickets:sum, costOfHotel:costsum}];
console.log(result);
Ответ 11
Это самый простой подход, который я мог бы придумать
var data = [{costOfAirtickets: 2500, costOfHotel: 1200},{costOfAirtickets: 1500, costOfHotel: 1000}];
var sum ={};
for(var obj in data){
for(var ele in data[obj]){
if(!data[obj].hasOwnProperty(ele)) continue;
if(sum[ele] === undefined){
sum[ele] = data[obj][ele];
}else{
sum[ele] = sum[ele] + data[obj][ele];
}
}
}
var arr = [sum];
console.log(arr);
Ответ 12
Моим упрощенным ответом было бы;
var data = [{costOfAirtickets: 2500, costOfHotel: 1200},
{costOfAirtickets: 1500, costOfHotel: 1000}],
res = data.reduce((p,c) => Object.entries(c).reduce((r,[k,v]) => (r[k]+=v, r), p));
console.log(res);
Ответ 13
var data = [{costOfAirtickets: 2500, costOfHotel: 1200},{costOfAirtickets: 1500, costOfHotel: 1000}];
var result = [data.reduce((acc, n) => {
for (var prop in n) {
if (acc[prop]) acc[prop] += n[prop];
else acc[prop] = n[prop];
}
return acc;
}, {})]
console.log(result)
Ответ 14
Lodash
Использование lodash
reduce и _.mergeWith это один лайнер:
var data = [{costOfAirtickets: 2500, costOfHotel: 1200}, {costOfAirtickets: 1500, costOfHotel: 1000}]
var result = _.reduce(data, (r,c) => _.mergeWith(r, c, (o = 0, s) => o + s), {})
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>