143 votes

Comment additionner les valeurs d'un objet JavaScript ?

Je voudrais faire la somme des valeurs d'un objet.

J'ai l'habitude de python où ce serait juste :

sample = { 'a': 1 , 'b': 2 , 'c':3 };
summed =  sum(sample.itervalues())     

Le code suivant fonctionne, mais c'est beaucoup de code :

function obj_values(object) {
  var results = [];
  for (var property in object)
    results.push(object[property]);
  return results;
}

function list_sum( list ){
  return list.reduce(function(previousValue, currentValue, index, array){
      return previousValue + currentValue;
  });
}

function object_values_sum( obj ){
  return list_sum(obj_values(obj));
}

var sample = { a: 1 , b: 2 , c:3 };
var summed =  list_sum(obj_values(a));
var summed =  object_values_sum(a)

Est-ce que j'ai raté quelque chose d'évident, ou est-ce que c'est juste comme ça ?

15voto

Honnêtement, compte tenu de nos "temps modernes", j'opterais pour une approche de programmation fonctionnelle chaque fois que possible, comme ceci :

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

Notre accumulateur acc en commençant par une valeur de 0, accumule toutes les valeurs bouclées de notre objet. Cela présente l'avantage supplémentaire de ne dépendre d'aucune variable interne ou externe ; c'est une fonction constante qui ne peut donc pas être accidentellement écrasée... une victoire pour ES2015 !

13voto

jbabey Points 20696

Une raison pour laquelle vous n'utilisez pas une simple for...in boucle ?

var sample = { a: 1 , b: 2 , c:3 };
var summed = 0;

for (var key in sample) {
    summed += sample[key];
};

http://jsfiddle.net/vZhXs/

3voto

let prices = {
  "apple": 100,
  "banana": 300,
  "orange": 250
};

let sum = 0;
for (let price of Object.values(prices)) {
  sum += price;
}

alert(sum)

1voto

Je suis un peu en retard sur la fête, mais si vous avez besoin d'une solution plus robuste et plus souple, voici ma contribution. Si vous voulez additionner seulement une propriété spécifique dans un combo objet/rayon imbriqué, ainsi qu'exécuter d'autres méthodes d'agrégation, alors voici une petite fonction que j'ai utilisée sur un projet React :

var aggregateProperty = function(obj, property, aggregate, shallow, depth) {
    //return aggregated value of a specific property within an object (or array of objects..)

    if ((typeof obj !== 'object' && typeof obj !== 'array') || !property) {
        return;
    }

    obj = JSON.parse(JSON.stringify(obj)); //an ugly way of copying the data object instead of pointing to its reference (so the original data remains unaffected)
    const validAggregates = [ 'sum', 'min', 'max', 'count' ];
    aggregate = (validAggregates.indexOf(aggregate.toLowerCase()) !== -1 ? aggregate.toLowerCase() : 'sum'); //default to sum

    //default to false (if true, only searches (n) levels deep ignoring deeply nested data)
    if (shallow === true) {
        shallow = 2;
    } else if (isNaN(shallow) || shallow < 2) {
        shallow = false;
    }

    if (isNaN(depth)) {
        depth = 1; //how far down the rabbit hole have we travelled?
    }

    var value = ((aggregate == 'min' || aggregate == 'max') ? null : 0);
    for (var prop in obj) {
        if (!obj.hasOwnProperty(prop)) {
            continue;
        }

        var propValue = obj[prop];
        var nested = (typeof propValue === 'object' || typeof propValue === 'array');
        if (nested) {
            //the property is an object or an array

            if (prop == property && aggregate == 'count') {
                value++;
            }

            if (shallow === false || depth < shallow) {
                propValue = aggregateProperty(propValue, property, aggregate, shallow, depth+1); //recursively aggregate nested objects and arrays
            } else {
                continue; //skip this property
            }
        }

        //aggregate the properties value based on the selected aggregation method
        if ((prop == property || nested) && propValue) {
            switch(aggregate) {
                case 'sum':
                    if (!isNaN(propValue)) {
                        value += propValue;
                    }
                    break;
                case 'min':
                    if ((propValue < value) || !value) {
                        value = propValue;
                    }
                    break;
                case 'max':
                    if ((propValue > value) || !value) {
                        value = propValue;
                    }
                    break;
                case 'count':
                    if (propValue) {
                        if (nested) {
                            value += propValue;
                        } else {
                            value++;
                        }
                    }
                    break;
            }
        }
    }

    return value;
}

Il est récursif, non ES6, et il devrait fonctionner dans la plupart des navigateurs semi-modernes. Vous l'utilisez comme ceci :

const onlineCount = aggregateProperty(this.props.contacts, 'online', 'count');

Ventilation des paramètres :

obj. \= soit un objet, soit un tableau
propriété \= la propriété dans les objets/rays imbriqués sur laquelle vous souhaitez exécuter la méthode d'agrégation
agrégat \= la méthode d'agrégation (somme, min, max, ou compte)
peu profond \= peut être défini comme vrai/faux ou comme une valeur numérique.
profondeur \= doit être laissé nul ou indéfini (il est utilisé pour suivre les rappels récursifs ultérieurs).

Shallow peut être utilisé pour améliorer les performances si vous savez que vous n'aurez pas besoin de rechercher des données profondément imbriquées. Par exemple, si vous avez le tableau suivant :

[
    {
        id: 1,
        otherData: { ... },
        valueToBeTotaled: ?
    },
    {
        id: 2,
        otherData: { ... },
        valueToBeTotaled: ?
    },
    {
        id: 3,
        otherData: { ... },
        valueToBeTotaled: ?
    },
    ...
]

Si vous souhaitez éviter de parcourir en boucle la propriété otherData puisque la valeur que vous allez agréger n'est pas imbriquée aussi profondément, vous pouvez définir shallow sur true.

1voto

Utiliser Lodash

 import _ from 'Lodash';

 var object_array = [{a: 1, b: 2, c: 3}, {a: 4, b: 5, c: 6}];

 return _.sumBy(object_array, 'c')

 // return => 9

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X