Суммировать все данные в массиве объектов в новый массив объектов

У меня есть массив объектов, который выглядит так:

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>