2014-09-24 17 views
17

Underscore.js fornisce _.each e _.map sulle raccolte, che è bello, ma ho bisogno di scorrere su tutti gli attributi del mio oggetto. Devo modificare i valori e conservare le chiavi. Per esempio. Ho qualcosa di simile: {a:1, b:2, c:3} e ho bisogno di eseguire un'operazione che modifica il valore ma mantiene le chiavi. Diciamo che calcolerò i quadrati, dovrei ottenere {a:1, b:4, c:9}. La domanda è: come farlo usando il carattere di sottolineatura (non interessato a vanilla javascript)? Mi piacerebbe un metodo come:Iterare sugli attributi dell'oggetto e modificarli

var a = {a:1, b:2, c:3} 
_.magic(a, function(item){ return item*item; }); 

Inoltre, sarebbe bello se questo fosse possibile catena di esso, dal momento che sto facendo una mappa, risultato discarica di eseguire ogni e quindi utilizzare di nuovo una mappa (in quanto Ho bisogno di).

risposta

14

ho guardato un po 'di più in alcuni dei miei frammenti per vedere se c'era la possibilità di mutare l'oggetto originale, ma non ho trovato nulla di interessante, così mi piacerebbe andare con this: \

var original = {a:1, b:2, c:3}; 
var squaredValues = _.object(_.map(original, function (value, key) { 
    return [key, value * value]; 
})); 

Spero però che ci sia una soluzione più elegante.

1

Grandi grazie a Javier92 che mi ha indicato la soluzione giusta.

In ogni caso, non mi piace utilizzare un metodo di sottolineatura che utilizza altri due metodi di sottolineatura (non è leggibile più di tanto), così mi si avvicinò con una semplice funzione wrapper che viene miscelato in in sottolineatura:

// mixin to make our new function available via _ 
_.mixin({ 
    updateAttributes: function(object, iteratee) { 
     return _.object(_.map(object, function (value, key) { 
      return [key, iteratee(value)]; 
     })); 
    } 
}); 

uso da qualche parte nel codice:

_.updateAttributes({a:1, b:2, c:3}, function(item){ return item*item; }) 
// Object {a: 1, b: 4, c: 9} 

non poteva pensare ad una funzione di una sola parola (probabilmente c'è qualcosa di meglio di updateAttributes).

+6

Lo-Dash ha questo esempio [_.mapValues] (http : //lodash.com/docs#mapValues) –

33

_.mapObject (added in version 1.8) è esattamente quello che stai cercando.


Per le versioni precedenti, possono mutare l'oggetto originale utilizzando il terzo argomento alla _.each callback.

_.each({a:1, b:2, c:3}, function(value, key, obj) { obj[key] = value * value; }); 

Utilizzando _.reduce con una nota iniziale, in grado di creare un nuovo marchio oggetto pure.

_.reduce({a:1, b:2, c:3}, function(memo, value, key) { 
    memo[key] = value * value; 
    return memo; 
}, {}); 

Preferirei l'approccio _.reduce. Un semplice mixin lo farà comportarsi esattamente come _.map.

_.mixin({ 
    magic: function(obj, iterator, context) { 
     return _.reduce(obj, function(memo, value, key) { 
      memo[key] = iterator.call(context, value, key, obj); 
      return memo; 
     }, {}); 
    } 
}); 
3

Come Justin detto _.mapObjectpotrebbe essere quello che stavate cercando. Ma crea un nuovo oggetto (che si estende {}) che potrebbe non essere quello che desideri (ad esempio se non è un semplice oggetto come new THREE.Vector3()), Qui non va bene sostituire l'oggetto originale con qualcosa di diverso.

Per quel caso (modificando i valori in luogo nel dell'oggetto dato) basta usare _.each con il terzo parametro della funzione iteratee:

_.each(complexObject, function(value, key, obj) { 
    obj[key] = value * value; 
}); 
Problemi correlati