Il existe une bonne méthode Array reduce()
pour obtenir une valeur du Array. Exemple:
[0,1,2,3,4].reduce(function(previousValue, currentValue, index, array){
return previousValue + currentValue;
});
Quelle est la meilleure façon d'obtenir la même chose avec des objets? J'aimerais faire ceci:
{
a: {value:1},
b: {value:2},
c: {value:3}
}.reduce(function(previous, current, index, array){
return previous.value + current.value;
});
Cependant, Object ne semble pas avoir de reduce()
méthode implémentée.
javascript
arrays
object
reduce
Pavel S.
la source
la source
Underscore.js
?reduce
méthode. Je vérifierais là-bas. Cependant, la solution ne semble pas si difficile._
a une réduction pour les objets. Je ne sais pas si cela fonctionne par accident ou si le support d'objet était intentionnel, mais en effet, vous pouvez passer un objet comme dans l'exemple de cette question, et il le fera (conceptuellement)for..in
, en appelant votre fonction d'itérateur avec les valeurs trouvées à chaque clé.Réponses:
Ce que vous voulez réellement dans ce cas, ce sont les fichiers
Object.values
. Voici une implémentation ES6 concise dans cet esprit:const add = { a: {value:1}, b: {value:2}, c: {value:3} } const total = Object.values(add).reduce((t, {value}) => t + value, 0) console.log(total) // 6
ou simplement:
const add = { a: 1, b: 2, c: 3 } const total = Object.values(add).reduce((t, n) => t + n) console.log(total) // 6
la source
Une option serait de
reduce
lakeys()
:var o = { a: {value:1}, b: {value:2}, c: {value:3} }; Object.keys(o).reduce(function (previous, key) { return previous + o[key].value; }, 0);
Avec cela, vous voudrez spécifier une valeur initiale ou le 1er tour sera
'a' + 2
.Si vous voulez que le résultat soit un Object (
{ value: ... }
), vous devrez initialiser et renvoyer l'objet à chaque fois:Object.keys(o).reduce(function (previous, key) { previous.value += o[key].value; return previous; }, { value: 0 });
la source
@babel/plugin-proposal-object-rest-spread
plugin, j'ai réparti la valeur de l'accumulateur dans retour de réduire et cela fonctionne comme un charme, mais je me demandais si je faisais quelque chose de mal, parce que je passais l'obejct à la valeur initiale de réduire et votre réponse m'a prouvé que j'avais fait la bonne chose!Implémentation ES6: Object.entries ()
const o = { a: {value: 1}, b: {value: 2}, c: {value: 3} }; const total = Object.entries(o).reduce(function (total, pair) { const [key, value] = pair; return total + value; }, 0);
la source
Object.entries(o); // returns [['value',1],['value',2],['value',3]]
function (total, pair)
pourfunction (total, [key, value])
entries
soit une façon plus propre de faire celakeys
, il est moins performant. hackernoon.comTout d'abord, vous ne comprenez pas tout à fait la valeur précédente de la réduction .
Dans votre pseudo-code que vous avez
return previous.value + current.value
, laprevious
valeur sera donc un nombre lors du prochain appel, pas un objet.Deuxièmement,
reduce
c'est une méthode Array, pas celle d'un objet, et vous ne pouvez pas vous fier à l'ordre lorsque vous itérez les propriétés d'un objet (voir: https://developer.mozilla.org/en-US/docs/ JavaScript / Reference / Statements / for ... in , cela s'applique également à Object.keys ); je ne suis donc pas sûr que l'applicationreduce
sur un objet ait du sens.Cependant, si l'ordre n'est pas important, vous pouvez avoir:
Object.keys(obj).reduce(function(sum, key) { return sum + obj[key].value; }, 0);
Ou vous pouvez simplement mapper la valeur de l'objet:
Object.keys(obj).map(function(key) { return this[key].value }, obj).reduce(function (previous, current) { return previous + current; });
PS dans ES6 avec la syntaxe de la fonction grosse flèche (déjà dans Firefox Nightly), vous pourriez réduire un peu:
Object.keys(obj).map(key => obj[key].value).reduce((previous, current) => previous + current);
la source
1:
[{value:5}, {value:10}].reduce((previousValue, currentValue) => { return {value: previousValue.value + currentValue.value}}) >> Object {value: 15}
2:
[{value:5}, {value:10}].map(item => item.value).reduce((previousValue, currentValue) => {return previousValue + currentValue }) >> 15
3:
[{value:5}, {value:10}].reduce(function (previousValue, currentValue) { return {value: previousValue.value + currentValue.value}; }) >> Object {value: 15}
la source
Un objet peut être transformé en tableau avec: Object.entries () , Object.keys () , Object.values () , puis être réduit en tableau. Mais vous pouvez également réduire un objet sans créer le tableau intermédiaire.
J'ai créé une petite bibliothèque d' aide pour travailler avec des objets.
Il a une
reduce
fonction qui fonctionne très bien comme Array.prototype.reduce () :export const reduce = (dict, reducer, accumulator) => { for (const key in dict) accumulator = reducer(accumulator, dict[key], key, dict); return accumulator; };
Vous pouvez également l'attribuer à:
Object.reduce = reduce;
car cette méthode est très utile!
La réponse à votre question serait donc:
const result = Object.reduce( { a: {value:1}, b: {value:2}, c: {value:3}, }, (accumulator, current) => (accumulator.value += current.value, accumulator), // reducer function must return accumulator {value: 0} // initial accumulator value );
la source
Étendez Object.prototype.
Object.prototype.reduce = function( reduceCallback, initialValue ) { var obj = this, keys = Object.keys( obj ); return keys.reduce( function( prevVal, item, idx, arr ) { return reduceCallback( prevVal, item, obj[item], obj ); }, initialValue ); };
Exemple d'utilisation.
var dataset = { key1 : 'value1', key2 : 'value2', key3 : 'value3' }; function reduceFn( prevVal, key, val, obj ) { return prevVal + key + ' : ' + val + '; '; } console.log( dataset.reduce( reduceFn, 'initialValue' ) ); 'Output' == 'initialValue; key1 : value1; key2 : value2; key3 : value3; '.
n'Joy it, les gars !! ;-)
la source
Object.entries()
en 2021Vous pouvez utiliser une expression de générateur (prise en charge dans tous les navigateurs depuis des années maintenant et dans Node) pour obtenir les paires clé-valeur dans une liste sur laquelle vous pouvez réduire:
>>> a = {"b": 3} Object { b=3} >>> [[i, a[i]] for (i in a) if (a.hasOwnProperty(i))] [["b", 3]]
la source
Si vous pouvez utiliser un tableau, utilisez un tableau, la longueur et l'ordre d'un tableau valent la moitié de sa valeur.
function reducer(obj, fun, temp){ if(typeof fun=== 'function'){ if(temp== undefined) temp= ''; for(var p in obj){ if(obj.hasOwnProperty(p)){ temp= fun(obj[p], temp, p, obj); } } } return temp; } var O={a:{value:1},b:{value:2},c:{value:3}} reducer(O, function(a, b){return a.value+b;},0);
/ * valeur renvoyée: (Number) 6 * /
la source
Ce n'est pas très difficile à mettre en œuvre vous-même:
function reduceObj(obj, callback, initial) { "use strict"; var key, lastvalue, firstIteration = true; if (typeof callback !== 'function') { throw new TypeError(callback + 'is not a function'); } if (arguments.length > 2) { // initial value set firstIteration = false; lastvalue = initial; } for (key in obj) { if (!obj.hasOwnProperty(key)) continue; if (firstIteration) firstIteration = false; lastvalue = obj[key]; continue; } lastvalue = callback(lastvalue, obj[key], key, obj); } if (firstIteration) { throw new TypeError('Reduce of empty object with no initial value'); } return lastvalue; }
En action:
var o = {a: {value:1}, b: {value:2}, c: {value:3}}; reduceObj(o, function(prev, curr) { prev.value += cur.value; return prev;}, {value:0}); reduceObj(o, function(prev, curr) { return {value: prev.value + curr.value};}); // both == { value: 6 }; reduceObj(o, function(prev, curr) { return prev + curr.value; }, 0); // == 6
Vous pouvez également l'ajouter au prototype Object:
if (typeof Object.prototype.reduce !== 'function') { Object.prototype.reduce = function(callback, initial) { "use strict"; var args = Array.prototype.slice(arguments); args.unshift(this); return reduceObj.apply(null, args); } }
la source
Comme cela n'a pas encore été confirmé dans une réponse, Underscore
reduce
fonctionne également pour cela._.reduce({ a: {value:1}, b: {value:2}, c: {value:3} }, function(prev, current){ //prev is either first object or total value var total = prev.value || prev return total + current.value })
Remarque,
_.reduce
retournera la seule valeur (objet ou autre) si l'objet liste n'a qu'un seul élément, sans appeler la fonction d'itérateur._.reduce({ a: {value:1} }, function(prev, current){ //not called }) //returns {value: 1} instead of 1
la source
Essayez cette fonction de flèche à une ligne
Object.values(o).map(a => a.value, o).reduce((ac, key, index, arr) => ac+=key)
la source
Essaye celui-là. Il triera les nombres d'autres variables.
const obj = { a: 1, b: 2, c: 3 }; const result = Object.keys(obj) .reduce((acc, rec) => typeof obj[rec] === "number" ? acc.concat([obj[rec]]) : acc, []) .reduce((acc, rec) => acc + rec)
la source