151 votes

Carte sur objet préservant les clés

La fonction map dans underscore.js, si appelée avec un objet javascript, renvoie un tableau de valeurs mappées à partir des valeurs de l'objet.

_.map({one: 1, two: 2, three: 3}, function(num, key){ return num * 3; });
=> [3, 6, 9]

Y a-t-il un moyen de conserver les clés? c'est-à-dire, je veux une fonction qui renvoie

{one: 3, two: 6, three: 9}

254voto

GG. Points 3063

Avec Souligner

Souligner fournit une fonction _.mapObject pour mapper les valeurs et préserver les clés.

_.mapObject({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; });

// => { one: 3, two: 6, three: 9 }

<strong><a href="http://jsfiddle.net/tANuM/81">DEMO</a></strong>


Avec Lodash

Lodash fournit une fonction _.mapValues pour mapper les valeurs et préserver les clés.

_.mapValues({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; });

// => { one: 3, two: 6, three: 9 }

<strong><a href="https://jsfiddle.net/rgzsu1tL/1">DEMO</a></strong>

59voto

xuanji Points 897

J'ai réussi à trouver la fonction requise dans lodash, une bibliothèque d'utilitaires similaire à underscore.

http://lodash.com/docs#mapValues

_.mapValues(object, [callback=identity], [thisArg])

Crée un objet avec les mêmes clés que l'objet et les valeurs générées en faisant passer chaque propriété énumérable de l'objet à travers le callback. Le rappel est lié à thisArg et invoqué avec trois arguments; (valeur, clé, objet).

20voto

leOm Points 20

Que diriez-vous de cette version en JS natif (ES6 / ES2015) ?

let newObj = Object.assign(...Object.keys(obj).map(k => ({[k]: obj[k] * 3})));

jsbin

Si vous souhaitez parcourir de manière récursive un objet (cartographier un objet imbriqué), vous pouvez le faire ainsi:

const mapObjRecursive = (obj) => {
  Object.keys(obj).forEach(key => {
    if (typeof obj[key] === 'object') obj[key] = mapObjRecursive(obj[key]);
    else obj[key] = obj[key] * 3;
  });
  return obj;
};

jsbin

Depuis ES7 / ES2016, vous pouvez utiliser Object.entries au lieu de Object.keys de cette manière:

let newObj = Object.assign(...Object.entries(obj).map(([k, v]) => ({[k]: v * 3})));

Et depuis ES2019, vous pouvez utiliser Object.fromEntries.

let newObj = Object.fromEntries(Object.entries(obj).map(([k, v]) => ([k, v * 3])))

19voto

kunalgolani Points 11
var mapped = _.reduce({ one: 1, two: 2, three: 3 }, function(obj, val, key) {
    obj[key] = val*3;
    return obj;
}, {});

console.log(mapped);

13voto

Rayjax Points 1117

Je sais que c'est old, mais maintenant Underscore a une nouvelle map pour les objets :

_.mapObject(object, iteratee, [context]) 

Bien sûr, vous pouvez créer une map flexible pour les tableaux et les objets

_.fmap = function(arrayOrObject, fn, context){
    if(this.isArray(arrayOrObject))
      return _.map(arrayOrObject, fn, context);
    else
      return _.mapObject(arrayOrObject, fn, context);
}

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