Mejor forma de sumr el valor de una propiedad en una matriz

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 sumr 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/

Sé que esta pregunta tiene una respuesta aceptada, pero pensé en agregar una alternativa que utiliza array.reduce , viendo que sumr 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'); 

Violín

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. 

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 syntax 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 progtwigción funcional y ES2015! 🙂

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

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 sumr es ‘valor’.

 _.sumBy(objects, 'value'); _.sumBy(objects, function(o) { return o.value; }); 

Ambos funcionarán.

también puede usar Array.prototype.forEach ()

 let totalAmount = 0; $scope.traveler.forEach( data => totalAmount = totalAmount + data.Amount); return totalAmount; 

Ya estaba usando jquery. Pero creo que es lo suficientemente intuitivo como para tener:

 var total_amount = 0; $.each(traveler, function( i, v ) { total_amount += v.Amount ; }); 

Esto es básicamente una versión abreviada de la respuesta de @ akhouri.