Tengo un objeto:
myObject = { 'a': 1, 'b': 2, 'c': 3 }
Estoy buscando un método nativo, similar al Array.prototype.map
que se usaría de la siguiente manera:
newObject = myObject.map(function (value, label) {
return value * value;
});
// newObject is now { 'a': 1, 'b': 4, 'c': 9 }
¿JavaScript tiene esa map
función para los objetos? (Quiero esto para Node.JS, por lo que no me importan los problemas entre navegadores).
javascript
node.js
functional-programming
map-function
Randomblue
fuente
fuente
Object.keys
, que no tiene un orden bien definido. Eso puede ser problemático, sugiero usar en suObject.getOwnPropertyNames
lugar.Object.keys
yObject.getOwnPropertyNames
. Ver developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Object.keys
depende de la implementación. Ver stackoverflow.com/a/30919039/1529630Respuestas:
No hay nativos
map
para elObject
objeto, pero ¿qué tal esto:Pero podría iterar fácilmente sobre un objeto usando
for ... in
:Actualizar
Mucha gente menciona que los métodos anteriores no devuelven un nuevo objeto, sino que operan en el objeto mismo. Para el caso, quería agregar otra solución que devuelva un nuevo objeto y deje el objeto original como está:
Array.prototype.reduce
reduce una matriz a un solo valor al fusionar un poco el valor anterior con el actual. La cadena se inicializa con un objeto vacío{}
. En cada iteraciónmyObject
se agrega una nueva clave de con el doble de la clave como valor.Actualizar
Con las nuevas características de ES6, hay una forma más elegante de expresar
objectMap
.fuente
map
correctamente porque no está haciendo unreturn
abuso, es abusivomap
como si fuera unaforEach
llamada. Si realmente lo hizo,return myObject[value] * 2
entonces el resultado sería una matriz que contiene los valores originales duplicados, en lugar de un objeto que contiene las claves originales con valores duplicados, siendo este último claramente lo que solicitó el OP..reduce
ejemplo está bien, pero en mi humilde opinión, todavía está muy lejos de la conveniencia de un.map
para objetos, ya que su.reduce
devolución de llamada no solo tiene que coincidir con la forma en que.reduce
funciona, sino que también requiere quemyObject
esté disponible en el ámbito léxico. Esto último en particular hace que sea imposible pasar una referencia de función en la devolución de llamada, lo que requiere una función anónima en su lugar..map
no es el método apropiado para usar cuando no va a usar la matriz asignada resultante; si solo desea efectos secundarios, como en su primer código, definitivamente debería usarloforEach
en su lugar.¿Qué tal una línea con asignación de variable inmediata en JS simple ( ES6 / ES2015 )?
Utilizando el operador de propagación y la sintaxis de nombre de clave calculada :
jsbin
Otra versión que usa reduce:
jsbin
Primer ejemplo como función:
jsbin
Si desea asignar un objeto anidado de forma recursiva en un estilo funcional , puede hacerlo así:
jsbin
O más imperativamente, así:
jsbin
Desde ES7 / ES2016 puede usar en
Object.entries()
lugar de,Object.keys()
por ejemplo, así:Se introdujo ES2019
Object.fromEntries()
, lo que simplifica esto aún más:Propiedades heredadas y la cadena del prototipo:
En alguna situación rara, es posible que deba asignar un objeto de clase que tenga propiedades de un objeto heredado en su cadena de prototipo . En tales casos
Object.keys()
no funcionará, porqueObject.keys()
no enumera las propiedades heredadas . Si necesita asignar propiedades heredadas , debe usarfor (key in myObj) {...}
.Aquí hay un ejemplo de un objeto que hereda las propiedades de otro objeto y cómo
Object.keys()
no funciona en ese escenario.jsbin
Sin embargo, por favor, hágame un favor y evite la herencia . :-)
fuente
Object.keys
no enumera las propiedades heredadas. Te sugiero que agregues una advertencia.Object.entries({a: 1, b: 2, c: 3})
.(o, f)
como argumentos, pero su usoobj
en el cuerpo.Object.assign(...Object.entries(obj).map(([k, v]) => ({[k]: v * v})))
no funciona siobj
es un objeto vacío. Cambiar a:Object.assign({}, ...Object.entries(obj).map(([k, v]) => ({[k]: v * v})))
.No hay métodos nativos, pero lodash # mapValues hará el trabajo de manera brillante
fuente
Object.entries({a: 1, b: 2, c: 3})
para obtener una matriz._.map()
para obtener la clave como segundo argumento, como lo requiere el OP._.mapValues()
también proporciona la clave como el segundo argumento. Tampoco_.map()
funcionaría aquí, ya que solo devuelve matrices, no objetos:_.map({ 'a': 1, 'b': 2, 'c': 3}, n => n * 3) // [3, 6, 9]
Es bastante fácil escribir uno:
con código de ejemplo:
NB: esta versión también le permite (opcionalmente) establecer el
this
contexto para la devolución de llamada, al igual que elArray
método.EDITAR : modificado para eliminar el uso de
Object.prototype
, para garantizar que no entre en conflicto con ninguna propiedad existente nombradamap
en el objeto.fuente
map
, pero debo decir que la modificaciónObject.prototype
no me sienta bien, incluso si no es enumerable.Object.prototype
más que el riesgo (teórico) de colisión con otros métodos. FWIW, no puedo entender cómo la otra respuesta obtuvo tantos votos como tiene, está completamente mal.o = {map: true, image: false}
. Lo arriesgas solo por escribir eno.map(fn)
lugar demap(o,fn)
Puede usar
Object.keys
y luegoforEach
sobre la matriz de claves devuelta:O de una manera más modular:
Tenga en cuenta que
Object.keys
devuelve una matriz que contiene solo las propiedades enumerables propias del objeto, por lo que se comporta como unfor..in
bucle con unahasOwnProperty
marca de verificación.fuente
Esto es directo, y todos en la comunidad de JS lo saben. No debería ser esta funcionalidad:
Aquí está la implementación ingenua:
es muy molesto tener que implementar esto usted mismo todo el tiempo;)
Si quieres algo un poco más sofisticado, que no interfiera con la clase Object, prueba esto:
pero es seguro agregar esta función de mapa a Object, simplemente no agregue a Object.prototype.
fuente
Object
objeto global ? Solo tengoconst mapObject = (obj, fn) => { [...]; return ret; }
..map
generalmente se entiende como una interfaz Functor, y no existe una definición única de Functor para "Objeto" porque prácticamente cualquier cosa en JavaScript puede ser un Objeto, incluidas las cosas con sus propias interfaces / lógica .map muy distintas y definidas.Vine aquí buscando encontrar y responder para asignar un objeto a una matriz y obtuve esta página como resultado. En caso de que haya venido aquí buscando la misma respuesta que yo, así es como puede asignar y objetar a una matriz.
Puede usar map para devolver una nueva matriz del objeto de la siguiente manera:
fuente
Object.values(myObject)
La respuesta aceptada tiene dos inconvenientes:
Array.prototype.reduce
, porque reducir significa cambiar la estructura de un tipo compuesto, lo que no sucede en este caso.Un enfoque funcional ES6 / ES2015
Tenga en cuenta que todas las funciones se definen en forma de curry.
o
se reasigna. Dado que Javascript pasa los valores de referencia al compartir ,o
se genera una copia superficial de . Ahora podemos mutaro
dentroomap
sin mutaro
en el ámbito primario.map
se ignora el valor de retorno, porquemap
realiza una mutación deo
. Dado que este efecto secundario permanece dentroomap
y no es visible en el ámbito primario, es totalmente aceptable.Esta no es la solución más rápida, sino declarativa y reutilizable. Aquí está la misma implementación que una línea, sucinta pero menos legible:
Anexo: ¿por qué los objetos no son iterables por defecto?
ES2015 especificó el iterador y los protocolos iterables. Pero los objetos aún no son iterables y, por lo tanto, no se pueden mapear. La razón es la mezcla de datos y nivel de programa .
fuente
Array.prototype.reduce
. Todo lo que quiero ilustrar aquí es que la respuesta aceptada de alguna manera "abusa"Array.prototype.reduce
y cómo se podría implementar un mapeo puramente funcional. Si no está interesado en la programación funcional, simplemente ignore mi respuesta.fold
es más genérico que unmap
(functor). Sin embargo, este fue mi conocimiento desde mediados de 2016. Eso es media eternidad: DJavaScript acaba de recibir el nuevo
Object.fromEntries
método.Ejemplo
Explicación
El código anterior convierte el objeto en una matriz anidada (
[[<key>,<value>], ...]
) que puede asignar.Object.fromEntries
convierte la matriz de nuevo en un objeto.Lo bueno de este patrón es que ahora puede tener fácilmente en cuenta las claves de los objetos durante el mapeo.
Documentación
Object.fromEntries()
Object.entries()
Soporte de navegador
Object.fromEntries
actualmente solo es compatible con estos navegadores / motores , sin embargo, hay polyfills disponibles (por ejemplo, @ babel / polyfill ).fuente
Object.fromEntries
es lo contrario deObject.entries
.Object.entries
convierte un objeto en una lista de pares clave-valor.Object.fromEntries
convierte una lista de pares clave-valor en un objeto.Versión mínima (es6):
fuente
Object.entries(obj).reduce((a, [k, v]) => [a[k] = v * v, a], {})
, corchetes angulados en lugar de paréntesis.Object.entries(obj).reduce((a, [k, v]) => {a[k] = v * v; return a}, {})
Object.entries().reduce
es la mejor solución creo que con ES6 + .WOULD obtener más upvotes si se utiliza unreturn
comunicado en el reductor en lugar deimplicit return
ycomma
del operador - que está ordenada, pero difícil de leer en mi humilde opiniónPara el máximo rendimiento.
Si su objeto no cambia con frecuencia pero necesita iterarse con frecuencia, sugiero usar un mapa nativo como caché.
Object.entries ya funciona en Chrome, Edge, Firefox y beta Opera, por lo que es una característica a prueba de futuro. Es de ES7, así que polyfill lo https://github.com/es-shims/Object.entries para IE donde no funciona.
fuente
const fn = v => v * 2; const newObj = Object.entries(myObject).reduce((acc, [k,v]) => Object.assign({}, acc, {[k]: fn(v)}), {});
puede usar el
map
método yforEach
en matrices, pero si desea usarlo,Object
puede usarlo con un giro como el siguiente:Usando Javascript (ES6)
Usando jQuery
O puede usar otros bucles también como
$.each
método como el siguiente ejemplo:fuente
$
está jquery?El
map function
no existe en el,Object.prototype
sin embargo, puede emularlo asífuente
typeof callback === 'function'
absolutamente redundante. 1)map
no tiene sentido sin devolución de llamada 2) sicallback
no es una función, lamap
implementación suya solo se ejecuta sin sentido for-loop. Además,Object.prototype.hasOwnProperty.call( obj, key )
es un poco exagerado.Encontré esto como un primer elemento en una búsqueda en Google tratando de aprender a hacer esto, y pensé que compartiría para otras personas que encontraron esto recientemente la solución que encontré, que utiliza el paquete npm inmutable.
Creo que es interesante compartir porque inmutable utiliza la situación EXACTA del OP en su propia documentación: lo siguiente no es mi propio código, sino que se extrajo de la documentación actual de inmutable-js:
No es que Seq tenga otras propiedades ("Seq describe una operación diferida, lo que les permite encadenar eficientemente el uso de todos los métodos de recopilación de orden superior (como el mapa y el filtro) al no crear colecciones intermedias") y que otros datos inmutables de js las estructuras también pueden hacer el trabajo de manera bastante eficiente.
Cualquiera que use este método, por supuesto, tendrá que
npm install immutable
que leer los documentos:https://facebook.github.io/immutable-js/
fuente
EDITAR: la forma canónica de usar las nuevas funciones de JavaScript es:
¿Dónde
o
está algún objeto yf
es su función de mapeo? O podríamos decir, dada una función dea -> b
, y un objeto con valores de tipoa
, producir un objeto con valores de tipob
. Como una firma de pseudo tipo -La respuesta original fue escrita para demostrar un poderoso combinador,
mapReduce
que nos permite pensar en nuestra transformación de una manera diferentem
, la función de mapeo - le da la oportunidad de transformar el elemento entrante antes ...r
, la función reductora : esta función combina el acumulador con el resultado del elemento asignadoIntuitivamente,
mapReduce
crea un nuevo reductor que podemos conectar directamenteArray.prototype.reduce
. Pero, lo que es más importante, podemos implementar nuestra implementación de functor de objetos de manera simpleomap
utilizando el monoide de objetoObject.assign
y{}
.Observe que la única parte del programa que realmente tuvimos que escribir es la implementación de mapeo en sí misma:
¿Qué dice, dado un objeto conocido
o
y alguna clavek
, construir un objeto y cuya propiedad computadak
es el resultado de la llamadaf
en el valor de la clave,o[k]
.Echamos un vistazo al
mapReduce
potencial de secuenciación si primero hacemos un resumenoreduce
Todo funciona igual, pero ahora
omap
se puede definir en un nivel superior. Por supuesto, lo nuevoObject.entries
hace que esto parezca tonto, pero el ejercicio sigue siendo importante para el alumno.No verá todo el potencial
mapReduce
aquí, pero comparto esta respuesta porque es interesante ver cuántos lugares se puede aplicar. Si está interesado en cómo se deriva y otras formas en que podría ser útil, consulte esta respuesta .fuente
Map
yMap.entries
, OK: D. Estoy cansado de abusar de objetos simples como tipos de datos de mapas.Map
debe usarse donde / cuando sea posible, pero no reemplaza totalmente la necesidad de usar estos procedimientos en objetos JS simples aunque: DBasado en la respuesta de @Amberlamps, aquí hay una función de utilidad (como comentario, se veía feo)
y el uso es:
fuente
fuente
enumerable
el valor predeterminado esfalse
Mi respuesta se basa en gran medida en la respuesta mejor calificada aquí y espero que todos entiendan (también tengo la misma explicación en mi GitHub). Es por eso que su impedancia con el mapa funciona:
El propósito de la función es tomar un objeto y modificar el contenido original del objeto utilizando un método disponible para todos los objetos (objetos y matrices por igual) sin devolver una matriz. Casi todo dentro de JS es un objeto, y por esa razón los elementos más abajo en la tubería de herencia pueden usar técnicamente aquellos disponibles para aquellos en la línea (y al revés parece).
La razón por la que esto funciona se debe a que las funciones .map devuelven una matriz que REQUIERE que proporcione un RETORNO explícito o implícito de una matriz en lugar de simplemente modificar un objeto existente. Básicamente, engañas al programa para que piense que el objeto es una matriz usando Object.keys, que te permitirá utilizar la función de mapa con su actuación sobre los valores con los que están asociadas las teclas individuales (en realidad, accidentalmente devolví matrices pero lo arreglé). Mientras no haya un retorno en el sentido normal, no se creará una matriz con el objeto original intacto y modificado según lo programado.
Este programa en particular toma un objeto llamado imágenes y toma los valores de sus claves y agrega etiquetas de URL para usar dentro de otra función. Original es esto:
... y modificado es esto:
La estructura original del objeto se deja intacta, lo que permite el acceso normal a la propiedad siempre que no haya un retorno. NO haga que devuelva una matriz como normal y todo estará bien. El objetivo es REASIGNAR los valores originales (imágenes [clave]) a lo que se desea y no a nada más. Por lo que sé, para evitar la salida de la matriz, TIENE que haber REASIGNACIÓN de imágenes [clave] y no hay una solicitud implícita o explícita de devolver una matriz (la asignación de variables hace esto y me fallaba de un lado a otro).
EDITAR:
Para abordar su otro método con respecto a la creación de nuevos objetos para evitar modificar el objeto original (y parece que la reasignación sigue siendo necesaria para evitar crear accidentalmente una matriz como salida). Estas funciones usan sintaxis de flecha y son si simplemente desea crear un nuevo objeto para uso futuro.
La forma en que funcionan estas funciones es así:
mapFn toma la función que se agregará más tarde (en este caso (valor) => valor) y simplemente devuelve lo que esté almacenado allí como un valor para esa clave (o multiplicado por dos si cambia el valor de retorno como lo hizo) en mapFn ( obj) [clave],
y luego redefine el valor original asociado con la clave en el resultado [clave] = mapFn (obj) [clave]
y devuelve la operación realizada en el resultado (el acumulador ubicado en los corchetes iniciados al final de la función .reduce).
Todo esto se está realizando en el objeto elegido y TODAVÍA NO PUEDE haber una solicitud implícita de una matriz devuelta y solo funciona al reasignar valores, por lo que puedo decir. Esto requiere algo de gimnasia mental pero reduce las líneas de código necesarias como se puede ver arriba. La salida es exactamente la misma que se puede ver a continuación:
Tenga en cuenta que esto funcionó con NON-NUMBERS. PUEDE duplicar CUALQUIER objeto SIMPLEMENTE DEVOLVIENDO EL VALOR en la función mapFN.
fuente
La primera función responde a la pregunta. Crea un mapa.
La segunda función no crea un mapa. En su lugar, recorre las propiedades del objeto existente usando
hasOwnProperty()
. Esta alternativa de mapa puede ser una mejor solución en algunas situaciones.fuente
Si está interesado en hacer
map
ping no solo a los valores sino también a las claves, he escritoObject.map(valueMapper, keyMapper)
que se comporta de esta manera:fuente
npm install @mattisg/object.map
.También necesitaba una versión que permitiera modificar las claves (basada en las respuestas de @Amberlamps y @yonatanmn);
factObject =
Editar: ligero cambio para pasar en el objeto inicial {}. Permite que sea [] (si las teclas son enteras)
fuente
Específicamente, quería usar la misma función que estaba usando para las matrices de un solo objeto, y quería que fuera simple. Esto funcionó para mí:
fuente
var mapped = myMapFunction(item)
Para responder más de cerca a lo que precisamente solicitó el OP, el OP quiere un objeto:
tener un método de mapa
myObject.map
,La mejor respuesta de imho (medida en términos de " cerca de lo que se pregunta " + "no se necesita ES {5,6,7} innecesariamente") sería:
El código anterior evita el uso intencional de cualquier función de lenguaje, solo disponible en ediciones recientes de ECMAScript. Con el código anterior, el problema se puede resolver como esto:
Además de ser mal visto por algunos, sería una posibilidad insertar la solución en la cadena de prototipos como esta.
Algo que, cuando se realiza con supervisión cuidadosa, no debería tener ningún efecto negativo y no afectar el
map
método de otros objetos (es decir, el de Arraymap
).fuente
Primero, convierta su colección HTMLC usando Object.entries (colección). Entonces es un iterable, ahora puede usar el método .map en él.
referencia https://medium.com/@js_tut/calling-javascript-code-on-multiple-div-elements-without-the-id-attribute-97ff6a50f31
fuente
Definir una función mapEntries.
mapEntries toma una función de devolución de llamada que se llama en cada entrada del objeto con el valor de los parámetros, la clave y el objeto. Debería devolver un nuevo valor.
mapEntries debería devolver un nuevo objeto con los nuevos valores devueltos por la devolución de llamada.
Editar: una versión anterior no especificaba que esta no es una propiedad enumerable
fuente
Hey escribió una pequeña función de mapeador que podría ayudar.
fuente
Una versión diferente de esto es usar una función personalizada json stringify que también puede funcionar en objetos profundos. Esto podría ser útil si tiene la intención de publicarlo en el servidor de todos modos como json
fuente
Solo manejo cadenas para reducir las exenciones:
fuente
Mapeador de objetos en TypeScript
Me gustan los ejemplos que usan
Object.fromEntries
como este , pero aún así, no son muy fáciles de usar. Las respuestas que usanObject.keys
y luego buscankey
están haciendo múltiples búsquedas que pueden no ser necesarias.Desearía que hubiera una
Object.map
función, pero podemos crear la nuestra y llamarlaobjectMap
con la capacidad de modificar ambaskey
yvalue
:Uso (JavaScript):
Código (TypeScript):
Si no está utilizando TypeScript, copie el código anterior en TypeScript Playground para obtener el código JavaScript.
Además, la razón que pongo
keySelector
despuésvalSelector
en la lista de parámetros es porque es opcional.* Algunos créditos van a la respuesta de alexander-mills .
fuente
Esta función recorre recursivamente el objeto y las matrices de objetos. Los atributos se pueden eliminar si se devuelven indefinidos
fuente