javascript - array - Mejor forma de sumar el valor de una propiedad en una matriz
agrupar array javascript (7)
Solo otra toma, esto es para lo que NATIVE JAVASCRIPT funciona MAP y REDUCE fueron construidas para (Map and Reduce son potencias en muchos idiomas).
var traveler = [{description: ''Senior'', Amount: 50},
{description: ''Senior'', Amount: 50},
{description: ''Adult'', Amount: 75},
{description: ''Child'', Amount: 35},
{description: ''Infant'', Amount: 25}];
function amount(item){
return item.Amount;
}
function sum(prev, next){
return prev + next;
}
traveler.map(amount).reduce(sum);
// => 235;
// or use arrow functions
traveler.map(item => item.Amount).reduce((prev, next) => prev + next);
Nota : al hacer funciones más pequeñas por separado, tenemos la posibilidad de usarlas de nuevo.
// Example of reuse.
// Get only Amounts greater than 0;
// Also, while using Javascript, stick with camelCase.
// If you do decide to go against the standards,
// then maintain your decision with all keys as in...
// {description: ''Senior'', Amount: 50} would be
// {Description: ''Senior'', Amount: 50};
var travelers = [{description: ''Senior'', amount: 50},
{description: ''Senior'', amount: 50},
{description: ''Adult'', amount: 75},
{description: ''Child'', amount: 35},
{description: ''Infant'', amount: 0 }];
// I changed "Amount" to "amount" to match data.
function amount(item){
return item.amount;
}
travelers.filter(amount);
// => [{description: ''Senior'', amount: 50},
// {description: ''Senior'', amount: 50},
// {description: ''Adult'', amount: 75},
// {description: ''Child'', amount: 35}];
// Does not include "Infant" as 0 is falsey.
Tengo algo como esto:
$scope.traveler = [
{ description: ''Senior'', Amount: 50},
{ description: ''Senior'', Amount: 50},
{ description: ''Adult'', Amount: 75},
{ description: ''Child'', Amount: 35},
{ description: ''Infant'', Amount: 25 },
];
Ahora para tener una cantidad total de esta matriz, estoy haciendo algo como esto:
$scope.totalAmount = function(){
var total = 0;
for (var i = 0; i < $scope.traveler.length; i++) {
total = total + $scope.traveler[i].Amount;
}
return total;
}
Es fácil cuando solo hay una matriz, pero tengo otras matrices con un nombre de propiedad diferente que me gustaría resumir.
Estaría más feliz si pudiera hacer algo como esto:
$scope.traveler.Sum({ Amount });
Pero no sé cómo pasar esto de una manera que pueda reutilizarlo en el futuro de esta manera:
$scope.someArray.Sum({ someProperty });
Responder
Decidí usar la sugerencia de @ gruff-bunny, así que evité el prototipado del objeto nativo (Array)
Acabo de hacer una pequeña modificación en su respuesta para validar la matriz y el valor para sumar no es nulo, esta es mi implementación final:
$scope.sum = function (items, prop) {
if (items == null) {
return 0;
}
return items.reduce(function (a, b) {
return b[prop] == null ? a : a + b[prop];
}, 0);
};
Como es una matriz, puede agregar una función al prototipo de Array.
traveler = [
{ description: ''Senior'', Amount: 50},
{ description: ''Senior'', Amount: 50},
{ description: ''Adult'', Amount: 75},
{ description: ''Child'', Amount: 35},
{ description: ''Infant'', Amount: 25 },
];
Array.prototype.sum = function (prop) {
var total = 0
for ( var i = 0, _len = this.length; i < _len; i++ ) {
total += this[i][prop]
}
return total
}
console.log(traveler.sum("Amount"))
The Fiddle: http://jsfiddle.net/9BAmj/
No estoy seguro de que esto haya sido mencionado todavía. Pero hay una función lodash para eso. El fragmento debajo de donde el valor es su atributo para sumar es ''valor''.
_.sumBy(objects, ''value'');
_.sumBy(objects, function(o) { return o.value; });
Ambos funcionarán.
Pensé en poner mi granito de arena en esto: esta es una de esas operaciones que siempre debe ser puramente funcional, sin depender de ninguna variable externa. Algunos ya dieron una buena respuesta, usar reduce
es el camino a seguir aquí.
Dado que la mayoría de nosotros ya podemos permitirnos usar la sintaxis de ES2015, esta es mi proposición:
const sumValues = (obj) => Object.keys(obj).reduce((acc, value) => acc + obj[value], 0);
Lo estamos haciendo una función inmutable mientras estamos en ello. Lo que se reduce
aquí es simplemente esto: comience con un valor de 0
para el acumulador y agregue el valor del elemento en bucle actual.
¡Yay para la programación funcional y ES2015! :)
Sé que esta pregunta tiene una respuesta aceptada, pero pensé en developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… una alternativa que utiliza developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… , viendo que sumar una matriz es el ejemplo canónico para reducir:
$scope.sum = function(items, prop){
return items.reduce( function(a, b){
return a + b[prop];
}, 0);
};
$scope.travelerTotal = $scope.sum($scope.traveler, ''Amount'');
Siempre evito cambiar el método de prototipo y agregar una biblioteca, así que esta es mi solución:
Usar el método de prototipo Reducir Array es suficiente
// + operator for casting to Number
items.reduce((a, b) => +a + +b.price, 0);
también puede usar Array.prototype.forEach()
let totalAmount = 0;
$scope.traveler.forEach( data => totalAmount = totalAmount + data.Amount);
return totalAmount;