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.