web-dev-qa-db-fra.com

Carte sur les clés de préservation d'objet

La fonction map de underscore.js, si elle est 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 le faire conserver les clés? c'est-à-dire que je veux une fonction qui retourne

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

Avec Souligner

Le trait de soulignement fournit une fonction _.mapObject pour mapper les valeurs et conserver les clés.

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

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

DEMO


Avec Lodash

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

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

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

DEMO

217
GG.

J'ai réussi à trouver la fonction requise dans lodash, une bibliothèque d’utilitaires semblable au soulignement.

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 exécutant chaque propriété énumérable de l'objet via le rappel. Le rappel est lié à thisArg et appelé avec trois arguments; (valeur, clé, objet).

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

console.log(mapped);
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>
19
kunalgolani

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

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

Vous pouvez bien sûr créer une carte 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);
}
13
Rayjax

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

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

jsbin

Si vous voulez mapper sur un objet récursivement (map imbriqué obj), procédez comme suit:

_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_ comme ceci:

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

_. map renvoie un tableau, pas un objet.

Si vous voulez un objet, vous feriez mieux d'utiliser une fonction différente, comme each; si vous voulez vraiment utiliser la carte, vous pouvez faire quelque chose comme ceci:

Object.keys(object).map(function(value, index) {
   object[value] *= 3;
})

mais c'est déroutant, quand on voit map on peut s'attendre à avoir un tableau comme résultat et ensuite faire quelque chose avec.

3
Alberto Zaccagni

Je sais que cela fait longtemps, mais la solution la plus évidente via fold (ou réduire en js) est toujours manquante. Par souci d'exhaustivité, je vais la laisser ici:

function mapO(f, o) {
  return Object.keys(o).reduce((acc, key) => {
    acc[key] = f(o[key])
    return acc
  }, {})
}
2
Darwin

Je pense que vous voulez une fonction mapValues (pour mapper une fonction sur les valeurs d'un objet), qui est assez facile à implémenter vous-même:

mapValues = function(obj, f) {
  var k, result, v;
  result = {};
  for (k in obj) {
    v = obj[k];
    result[k] = f(v);
  }
  return result;
};
2
joyrexus

n correctif de mixage pour la carte de soulignement bug : P

_.mixin({ 
    mapobj : function( obj, iteratee, context ) {
        if (obj == null) return [];
        iteratee = _.iteratee(iteratee, context);
        var keys = obj.length !== +obj.length && _.keys(obj),
            length = (keys || obj).length,
            results = {},
            currentKey;
        for (var index = 0; index < length; index++) {
          currentKey = keys ? keys[index] : index;
          results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
        }
        if ( _.isObject( obj ) ) {
            return _.object( results ) ;
        } 
        return results;
    }
}); 

Une solution de contournement simple qui conserve la bonne clé et retourne sous forme d'objet. Il est toujours utilisé de la même manière que sur un invité, vous pouvez utiliser cette fonction pour remplacer la fonction bugy _.map.

ou simplement comme je l'ai utilisé comme mixin

_.mapobj ( options , function( val, key, list ) 
1
Pascal

Vous pouvez utiliser _.mapValues(users, function(o) { return o.age; }); dans Lodash et _.mapObject({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; }); dans le soulignement.

Découvrez la documentation croisée ici: http://jonathanpchen.com/underdash-api/#mapvalues-object-iteratee-identity

0
luxon