recorrer objetos objeto new metodos eliminar elementos elemento buscar array agregar javascript arrays lodash

javascript - new - Suma todos los datos en una matriz de objetos en una nueva matriz de objetos



recorrer array de objetos javascript (14)

Tengo una matriz de objetos que se parece a esto:

var data = [{costOfAirtickets: 2500, costOfHotel: 1200},{costOfAirtickets: 1500, costOfHotel: 1000}]

y quiero sumar cada elemento de la matriz para producir una matriz como esta:

var result = [{costOfAirtickets: 4000, costOfHotel: 3200}]

He utilizado un mapa y una función de reducción, pero solo pude sumar un elemento individual así:

data.map(item => ite.costOfAirtickets).reduce((prev, next)=>prev + next); // 22

En este momento, esto produce un valor único que no es lo que quiero según la explicación inicial.

¿Hay una manera de hacer esto en Javascript o probablemente con lodash.


Aquí hay un enfoque lodash

_(data).flatMap(_.entries).groupBy(0).mapValues(v=>_.sumBy(v, 1)).value()

Se sumará por todas las claves únicas.

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>

Envuelva su resultado en un [...] o use un .castArray() al final antes de desenvolverlo utilizando .value() en caso de que desee una matriz como resultado.


Este es el enfoque más fácil que podría pensar

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);


Intenta usar reducir solo como se muestra en el siguiente fragmento de código. Intenta evitar múltiples iteraciones. Espero que el fragmento de abajo ayuda!

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)


Mi respuesta simplista sería como;

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);

Una nota sobre el uso de .reduce() : si los elementos de la matriz y el valor acumulado son del mismo tipo, puede considerar no utilizar un valor inicial como acumulador y hacer su reducción con los elementos anterior ( p ) y actual ( c ). La reducción exterior en el fragmento anterior es de este tipo. Sin embargo, la reducción interna toma una matriz del par clave ( k ) valor ( v ) como [k,v] para devolver un objeto, por lo tanto, un valor inicial ( p ) es esencial.

El resultado es el valor acumulado como un objeto. Si lo necesita en una matriz, simplemente póngalo en una matriz como [res] .


No necesitas mapear la matriz, en realidad solo estás reduciendo las cosas dentro de ella.

const totalCostOfAirTickets: data.reduce((prev, next) => prev + next.costOfAirTickets, 0) const totalCostOfHotel: data.reduce((prev, next) => prev + next.costOfHotel, 0) const totals = [{totalCostOfAirTickets, totalCostOfHotel}]

De una vez, podrías hacer algo como

const totals = data.reduce((prev, next) => { prev.costOfAirTickets += next.costOfAirTickets; prev.costOfHotel += next.costOfHotel; }, {costOfAirTickets: 0, costOfHotel: 0})


Otra solución sería usar Map ( no Array.prototype.map ) ya que tiene varias diferencias notables en comparación con los objetos :

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())

Explicación

Bucle externo

Lo anterior primero itera sobre su matriz de data usando el método de reduce . Cada objeto dentro del cual me rcd como un registro, se distingue en el código a través de la variable, rcd .

Cada iteración de reduce devuelve un valor que se pasa como primer argumento a la siguiente iteración del bucle. En este caso, la collection parámetros contiene ese argumento, que es su conjunto de sumas.

Bucle interno

Dentro del ciclo de reduce , cada par clave / valor del registro se itera sobre el uso de forEach . Para obtener el par clave / valor se Object.entries método Object.entries . El uso de la desestructuración de matrices de estos argumentos se puede asignar directamente a las variables respectivas, key y value

Recuperando / estableciendo valores

A diferencia de un objeto primitivo, Map tiene sus propios métodos para obtener y configurar sus entradas utilizando get() y set() . Así que primero recupere la suma anterior usando get() , si no está establecida, entonces el valor predeterminado es 0 , que es lo que || 0 || 0 hace. En ese momento, puede asumir que la suma anterior es al menos 0 o mayor y agregarle el valor de la clave actual.

Alternativas al Mapa

Si encuentra que Map es un poco torpe, también puede usar un objeto similar como Set , que tiene muchos de los mismos métodos (excepto el get() ), o también podría usar un objeto primitivo (es decir, {} ) .


Para crear un valor resultante / reducido, debe usar el método .reduce() lugar de .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);


Podría reducir la matriz tomando un objeto para sumar.

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);


Puedes usar un simple bucle forEach() para eso:

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);


Usa Lodash para simplificar tu vida.

const _ = require(''lodash'') let keys = [''costOfAirtickets'', ''costOfHotel'']; let results = _.zipObject(keys, keys.map(key => _.sum( _.map(data, key)))) ... { costOfAirtickets: 4000, costOfHotel: 2200 }

Explicación:

  • _.sum(_.map(data, key)) : genera la suma de cada matriz
  • _.zipObject : _.zipObject los resultados con la suma de la matriz
  • el uso de keys.map() para la suma de cada clave como _.map no garantiza el orden.

Documentación:


Usando for..in para iterar el objeto y reduce para iterar la matriz

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)


map el objeto y calcular la suma y almacenarlo en otro.

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);


Lodash

Usando lodash reduce y _.mergeWith este es un liner:

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>

Solo ES6

Si NO desea mutar la matriz original, puede utilizar ES6 reduce , Object.entries y forEach esta forma:

var data = [{costOfAirtickets: 2500, costOfHotel: 1200}, {costOfAirtickets: 1500, costOfHotel: 1000}] // One liner var result1 = data.reduce((r, c) => !Object.entries(c).forEach(([key, value]) => r[key] = (r[key] || 0) + value) && r, {}) // More readable var result2 = data.reduce((r, c) => { Object.entries(c).forEach(([key, value]) => r[key] = (r[key] || 0) + value) return r }, {}) console.log(result1) console.log(result2)

Si no nos importa mutar la matriz de data inicial data entonces podemos tener una solución de una línea:

var data = [{costOfAirtickets: 2500, costOfHotel: 1200}, {costOfAirtickets: 1500, costOfHotel: 1000}] data.reduce((r, c) => !Object.entries(c).forEach(([key,value]) => r[key] += value) && r) console.log(data[0])

Más legible:

var data = [{costOfAirtickets: 2500, costOfHotel: 1200}, {costOfAirtickets: 1500, costOfHotel: 1000}] data.reduce((r, c) => { Object.entries(c).forEach(([key, value]) => r[key] += value) return r }) console.log(data[0])

La única diferencia entre los ejemplos de mutación y no de mutación es el valor inicial para la reduce (y también el hecho de que con la mutación usamos el índice 0 para acumular las sumas). En los mutantes no hay initial value mientras que en los otros, comenzamos con el objeto literal vacío.

si necesita que el resultado sea una matriz específicamente, devuelva [data] para los ejemplos de mutación y [result] para los ejemplos puros.


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)