2012-06-11 6 views
9

¿No existe una función ubicua/estándar de Javascript o Coffeescript que transforma los valores de un objeto/mapa/hash?Cualquier función `map` de Javascript o Coffeescript que transforma object * values ​​*?

jQuery has $.map pero produce Array s solamente.
Underscore has _.map pero también produce Array s solamente.

Para ser claro, una función como esta es lo que estoy buscando. (Este ejemplo está escrito en CoffeeScript no Javascript.)

# Transforms the values in a map. (Doesn't modify `obj` — returns a new map.) 
# Example usage: 
# mapObjVals({ a: 'aa', b: 'bb'}, (key, value) -> value + '_!') 
# --> { a: 'aa_!', b: 'bb_!' } 
mapObjVals = (obj, f) -> 
    obj2 = {} 
    for k, v of obj 
    obj2[k] = f k, v 
    obj2 
+1

Parece que has respondido a tu propia pregunta :) Solo asegúrate de usar 'para own k, v of obj' para evitar que te muerdan las extensiones de los prototipos. Yo usaría el bucle 'for' directamente en lugar de una función auxiliar, ya que esto es una ocurrencia rara. –

Respuesta

6

Si desea asignar un objeto a un objeto, es necesario utilizar un (terminología tradicional funcional) fold o reduce (nombre moderno común, utilizado por un guión), que construye un nuevo valor a partir de una colección:

_.reduce(obj, function(newObj, thisValue, thisKey) { 
     // modify newObj based on thisKey/thisValue 
     return newObj; 
     }, {}) 

la función pasa como el segundo argumento se llama una vez por par clave/valor. Se pasa en el objeto que se está construyendo como su primer argumento, seguido del valor actual, seguido de la clave asociada. Depende de la función modificar el objeto y devolver su nuevo valor.

El tercer argumento para _.reduce es el valor inicial del nuevo objeto, que se pasará con el primer par clave/valor; en este caso es un objeto/mapa/hash vacío {}.

Reduce/fold/inject se usa comúnmente para sumar valores. Básicamente, cada vez que desee construir un nuevo valor único de una colección. map es realmente solo un caso especial de reduce donde el valor supuestamente reducido es realmente otra colección del mismo tamaño que el original.

Para CoffeeScript, AFAIK, la lista de comprensiones siempre devuelve listas, incluso cuando se itera sobre un objeto. Por lo que es posible que desee consultar the CoffeeScript version of Underscore.

+0

¡Gracias! Obtuve mi ejemplo '+ '_!'' Trabajando con '_.reduce' como lo siguiente:' _ ({a: 'aa', b: 'bb'}). Reduce ((memo, value, index) -> memo [index] = value + '_!'; memo), {} ' – KajMagnus

+1

" Lamentablemente ", con' _.reduce', tengo que 1) devolver 'memo' desde el interior del iterador, y 2) pasar' { } 'to' reduce'. Entonces es algo más detallado. De hecho, mi función de ejemplo me resulta más fácil de entender: cuando leo 'mapObjVals ({a: 'aa', b: 'bb'}, (clave, valor) -> valor + '_!')' Entiendo bastante rápido lo que se está haciendo. – KajMagnus

+0

Sí, reducir es más detallado porque es más general; mapa puede implementarse fácilmente en términos de reducir. Ya sea que sienta la necesidad de escribir una función auxiliar para ocultar esa verbosidad depende de las preferencias personales. –

Cuestiones relacionadas