Betere manier om een eigenschapswaarde in een array op te tellen

Ik heb zoiets als dit:

$scope.traveler = [
            {  description: 'Senior', Amount: 50},
            {  description: 'Senior', Amount: 50},
            {  description: 'Adult', Amount: 75},
            {  description: 'Child', Amount: 35},
            {  description: 'Infant', Amount: 25 },
];

Om nu een totaalbedrag van deze array te hebben, doe ik zoiets als dit:

$scope.totalAmount = function(){
       var total = 0;
       for (var i = 0; i < $scope.traveler.length; i++) {
              total = total + $scope.traveler[i].Amount;
            }
       return total;
}

Het is gemakkelijk als er maar één array is, maar ik heb andere arrays met een andere eigenschapsnaam die ik zou willen optellen.

Ik zou gelukkiger zijn als ik zoiets als dit zou kunnen doen:

$scope.traveler.Sum({ Amount });

Maar ik weet niet hoe ik dit zo moet aanpakken dat ik het in de toekomst als volgt kan hergebruiken:

$scope.someArray.Sum({ someProperty });

Antwoord 1, autoriteit 100%

Bijgewerkt antwoord

Vanwege alle nadelen van het toevoegen van een functie aan het Array-prototype, update ik dit antwoord om een alternatief te bieden dat de syntaxis vergelijkbaar houdt met de syntaxis die oorspronkelijk in de vraag werd gevraagd.

class TravellerCollection extends Array {
    sum(key) {
        return this.reduce((a, b) => a + (b[key] || 0), 0);
    }
}
const traveler = new TravellerCollection(...[
    {  description: 'Senior', Amount: 50},
    {  description: 'Senior', Amount: 50},
    {  description: 'Adult', Amount: 75},
    {  description: 'Child', Amount: 35},
    {  description: 'Infant', Amount: 25 },
]);
console.log(traveler.sum('Amount')); //~> 235

Oorspronkelijk antwoord

Omdat het een array is, zou je een functie aan het array-prototype kunnen toevoegen.

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

De viool: http://jsfiddle.net/9BAmj/


Antwoord 2, autoriteit 91%

Ik weet dat deze vraag een geaccepteerd antwoord heeft, maar ik dacht dat ik een alternatief zou gebruiken dat gebruikmaakt van array.reduce, aangezien het optellen van een array het canonieke voorbeeld is voor reduce:

$scope.sum = function(items, prop){
    return items.reduce( function(a, b){
        return a + b[prop];
    }, 0);
};
$scope.travelerTotal = $scope.sum($scope.traveler, 'Amount');

Fiddle


Antwoord 3, autoriteit 97%

Nog een keer, dit is wat nativeJavaScript-functies mapen reducewerden gebouwd voor (Map en Reduce zijn krachtpatsers in vele talen).

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

Opmerking: door aparte kleinere functies te maken, krijgen we de mogelijkheid om ze opnieuw te gebruiken.

// 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 }];
// Directly above Travelers array I changed "Amount" to "amount" to match standards.
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.

Antwoord 4, autoriteit 71%

Ik vermijd altijd het wijzigen van de prototypemethode en het toevoegen van een bibliotheek, dus dit is mijn oplossing:

Het gebruik van de reduce Array-prototypemethode is voldoende

// + operator for casting to Number
items.reduce((a, b) => +a + +b.price, 0);

Antwoord 5, autoriteit 38%

Gebruik verminderen met destructuring om Bedrag op te tellen:

const traveler = [
  { description: 'Senior', Amount: 50 },
  { description: 'Senior', Amount: 50 },
  { description: 'Adult', Amount: 75 },
  { description: 'Child', Amount: 35 },
  { description: 'Infant', Amount: 25 },
];
console.log(traveler.reduce((n, {Amount}) => n + Amount, 0))

Antwoord 6, autoriteit 23%

Alternatief voor verbeterde leesbaarheid en gebruik van mapen reduce:

const traveler = [
    {  description: 'Senior', amount: 50 },
    {  description: 'Senior', amount: 50 },
    {  description: 'Adult', amount: 75 },
    {  description: 'Child', amount: 35 },
    {  description: 'Infant', amount: 25 },
];
const sum = traveler
  .map(item => item.amount)
  .reduce((prev, curr) => prev + curr, 0);

Herbruikbare functie:

const calculateSum = (obj, field) => obj
  .map(items => items.attributes[field])
  .reduce((prev, curr) => prev + curr, 0);

Antwoord 7, autoriteit 13%

Ik dacht dat ik mijn twee cent op dit moment zou laten vallen: dit is een van die operaties die altijd puur functioneel moeten zijn, niet afhankelijk zijn van externe variabelen. Een paar gaf al een goed antwoord, met behulp van reduceis de manier om hierheen te gaan.

Aangezien de meesten van ons zich al kunnen veroorloven om ES2015-syntaxis te gebruiken, hier is mijn propositie:

const sumValues = (obj) => Object.keys(obj).reduce((acc, value) => acc + obj[value], 0);

We maken het een onveranderlijke functie terwijl we erbij zijn. Wat reduceis hier gewoon dit:
Begin met een waarde van 0voor de accumulator en voeg de waarde van het huidige lus-item toe.

YAY voor functionele programmering en ES2015! 🙂


Antwoord 8, Autoriteit 13%

U kunt het volgende doen:

$scope.traveler.map(o=>o.Amount).reduce((a,c)=>a+c);

Antwoord 9, Autoriteit 10%

Het werkt voor mij in TypeScripten JavaScript:

let lst = [
     { description:'Senior', price: 10},
     { description:'Adult', price: 20},
     { description:'Child', price: 30}
];
let sum = lst.map(o => o.price).reduce((a, c) => { return a + c });
console.log(sum);

Antwoord 10, Autoriteit 6%

Ik weet niet zeker of dit al is genoemd. Maar er is een lodash functie voor dat. Fragment hieronder waar de waarde uw attribuut is voor de som is ‘waarde’.

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

Beide zullen werken.


Antwoord 11, autoriteit 2%

Van reeks objecten

function getSum(array, column)
  let values = array.map((item) => parseInt(item[column]) || 0)
  return values.reduce((a, b) => a + b)
}
foo = [
  { a: 1, b: "" },
  { a: null, b: 2 },
  { a: 1, b: 2 },
  { a: 1, b: 2 },
]
getSum(foo, a) == 3
getSum(foo, b) == 6

Antwoord 12, autoriteit 2%

kan ook Array.prototype.forEach()

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

Antwoord 13

Hier is een one-liner die ES6-pijlfuncties gebruikt.

const sumPropertyValue = (items, prop) => items.reduce((a, b) => a + b[prop], 0);
// usage:
const cart_items = [ {quantity: 3}, {quantity: 4}, {quantity: 2} ];
const cart_total = sumPropertyValue(cart_items, 'quantity');

Antwoord 14

Hoe array van objecten optellen met Javascript

const traveler = [
  {  description: 'Senior', Amount: 50},
  {  description: 'Senior', Amount: 50},
  {  description: 'Adult', Amount: 75},
  {  description: 'Child', Amount: 35},
  {  description: 'Infant', Amount: 25 }
];

const traveler = [
    {  description: 'Senior', Amount: 50},
    {  description: 'Senior', Amount: 50},
    {  description: 'Adult', Amount: 75},
    {  description: 'Child', Amount: 35},
    {  description: 'Infant', Amount: 25 },
];
function sum(arrayData, key){
   return arrayData.reduce((a,b) => {
  return {Amount : a.Amount + b.Amount}
})
}
console.log(sum(traveler))

Antwoord 15

Na het doornemen van deze antwoorden denk ik dat eigenlijk een for(of forEachof for ofmet await) loop is veel leesbaarder dan reduceof zelfs mapen reduce.
Denk aan:

  1. na 6 maanden terugkomen op deze code of deze door iemand anders onderhouden. Ik denk dat jouw benadering van het gebruik van een lus goed genoeg is.
  2. om deze functie in de toekomst uit te breiden, voor het geval u een valutaconversie of iets dergelijks wilt toevoegen. Dit in een oneliner doen is geen goed idee.
var traveler = [
  {Amount: 50,  description: 'Senior'},
  {Amount: 50,  description: 'Senior'},
  {Amount: 75,  description: 'Adult'},
  {Amount: 35,  description: 'Child'},
  {Amount: 25,  description: 'Infant'}
];
var sumFromArray = (propertyName, array) => {
  let sum = 0;
  array.forEach(item => {
    sum += item[propertyName] ?? 0;
  });
  return sum;
};
var sumOfTraveler = sumFromArray('Amount', traveler);
console.log(sumOfTraveler);

Antwoord 16

Ik gebruik al jQuery. Maar ik denk dat het intuïtief genoeg is om te hebben:

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

Dit is eigenlijk slechts een korte versie van @ Akhouri’s antwoord.


Antwoord 17

Hier is een oplossing, ik vind flexibeler:

function sumOfArrayWithParameter (array, parameter) {
  let sum = null;
  if (array && array.length > 0 && typeof parameter === 'string') {
    sum = 0;
    for (let e of array) if (e && e.hasOwnProperty(parameter)) sum += e[parameter];
  }
  return sum;
}

Gebruik het zo graag:

let sum = sumOfArrayWithParameter(someArray, 'someProperty');

Antwoord 18

Ik ben eerlijk gezegd gefrustreerd tijdens het lezen van alle code die werd gepost als een oplossing voor deze CUS Ik ben een nieuwe zijn en ik probeer een functionaliteit aan een eenvoudige app voor de praktijk toe te voegen. De eenvoudige manier om dit op te lossen is

let testArray = [5, 7, 8, 4];
function(){
sum = 0;
for(let i = 0; i < testArray.length; i++){
    sum += testArray[i];
}

// geeft u de som van de array

Other episodes