transformar objeto en matriz con lodash

165

¿Cómo puedo transformar un big objectto arraycon lodash?

var obj = {
  22: {name:"John", id:22, friends:[5,31,55], works:{books:[], films:[],}
  12: {name:"Ivan", id:12, friends:[2,44,12], works:{books:[], films:[],}
}

// transform to 
var arr = [{name:"John", id:22...},{name:"Ivan", id:12...}]
siavolt
fuente
@Mritunjay Sí, porque los documentos tienen una excelente visión general de la biblioteca ... no. Es solo una lista exhaustiva de funciones y revisar cada una de ellas podría ser una pérdida de tiempo si no hay una. La pregunta es justa.
Epirocks

Respuestas:

264

Tu puedes hacer

var arr = _.values(obj);

Para documentación ver aquí.

Daniel Schmidt
fuente
34
¿Qué pasa si desea conservar la clave como una propiedad? (en este ejemplo, si la idpropiedad no existiera y quisiera crearla en función de la clave de cada objeto.
Michael Liquori
8
Podría hacer algo como esto:var arr = _.values(_.mapKeys(obj, function(value, key) { value.id = key; return value; }));
Daniel Schmidt
1
@DanielSchmidt No estoy seguro de qué hice mal, pero esa muestra solo me devolvió 1 fila. :( Entonces, lo que hice fue empujar manualmente el returnvalor a una matriz como esta: const divisionsList = []; _.mapKeys(divisions, (value, key) => { divisionsList[key] = value; });agradecería cualquier comentario o sugerencia para mejorar este enfoque.
JohnnyQ
8
@JohnnyQ Creo que necesitarás usar mapValues ​​en su lugar, por ejemploconst toArrayWithKey = (obj, keyAs) => _.values(_.mapValues(obj, (value, key) => { value[keyAs] = key; return value; }));
orjan el
1
@orjan Sí, realmente descubrí esto, solo olvidé actualizar. Gracias por eso.
JohnnyQ
38
_.toArray(obj);

Salidas como:

[
  {
    "name": "Ivan",
    "id": 12,
    "friends": [
      2,
      44,
      12
    ],
    "works": {
      "books": [],
      "films": []
    }
  },
  {
    "name": "John",
    "id": 22,
    "friends": [
      5,
      31,
      55
    ],
    "works": {
      "books": [],
      "films": []
    }
  }
]"
Jivings
fuente
1
_.toArray () Funciona bien @jivings
Syed Zain Ali
44
para obtener solo valores es una buena opción, pero toArrayno hay forma de preservar las claves si es necesario.
Koushik Chatterjee
33

Una solución nativa moderna si alguien está interesado:

const arr = Object.keys(obj).map(key => ({ key, value: obj[key] }));

o (no IE):

const arr = Object.entries(obj).map(([key, value]) => ({ key, value }));
Dominic
fuente
2
¿Por qué no solo?Object.keys(obj).map(key=>({key,value: obj[key]}))
Koushik Chatterjee
1
Me gusta que ni siquiera el usuario lodash, ¡bien hecho señor!
HungryPipo
1
@Dominic Ahora cambiaste tu respuesta completa y la tomaste de mi comentario, incluso sin mencionarlo (lo editaste). Bien hecho 👏 😁😁
Koushik Chatterjee
1
@KoushikChatterjee lo agregó nuevamente
Dominic
2
¿Sería esto más útil? const arr = Object.keys(obj).map(id => ({ id, ...obj[id] })); esto traería todo el objeto a los datos devueltos no? (usando 'id' ya que el autor de la pregunta original quería almacenar su clave como id prop)
zabaat
20

Para mí, esto funcionó:

_.map(_.toPairs(data), d => _.fromPairs([d]));

Da vueltas

{"a":"b", "c":"d", "e":"f"} 

dentro

[{"a":"b"}, {"c":"d"}, {"e":"f"}]
No nueve
fuente
1
Necesitaba transformar un objeto en una matriz, de manera que cada clave / valor del objeto original fuera un objeto {clave: valor} en la matriz. _.toPairs (datos) toma el objeto {"a": "b", "c": "d", "e": "f"} y lo devuelve como una matriz de matrices como [["a": " b "], [" c ":" d "], [" e ":" f "]]. _.fromPairs hace lo contrario, toma una matriz con 2 elementos: ["a", "b"] y la devuelve como un objeto: {"a": "b"}. Usando _.map, iteré sobre la matriz si las matrices creadas por _.toPairs para transformarlo en una matriz de objetos con la ayuda de _.fromPairs.
NoNueve
1
Me alegro de haberme desplazado hacia abajo para ver esto. ¡Tu solución funcionó para mí! ¡Gracias!
Wale
@NoNine No necesita aplicar el mapa en una matriz (de la matriz), puede aplicarlo directamente en el objeto de entrada y devolver cada par de valores clave. _.map(data, (v,k)=>({[k]: v}))Consulte mi respuesta para obtener más detalles. _.toPairsy _fromPairses adicional e innecesario aquí.
Koushik Chatterjee
Esto no es para lo que está hecha la pregunta. porque es un poco difícil usar el resultado ya que cada entrada contiene una clave (que no sabes) y de nuevo debes pasar por alguna lógica (por ejemplo, Object.keys u Object.values) para cada entrada separada para obtener el valor de cada uno, si falta juguete para preservar las teclas a continuación, puede crear una matriz de objetos que stuctrured como[{key: 'someKey', val: 'The value'}, {....},...]
Koushik Chatterjee
13

Hay bastantes maneras de obtener el resultado que busca. Vamos a dividirlos en categorías:

Solo valores ES6 :

El método principal para esto es Object.values . Pero usando Object.keys y Array.map también podrías llegar al resultado esperado:

Object.values(obj)
Object.keys(obj).map(k => obj[k])

Clave y valor de ES6 :

Usando el mapa y las propiedades dinámicas / calculadas de ES6 y la desestructuración puede retener la clave y devolver un objeto del mapa.

Object.keys(obj).map(k => ({[k]: obj[k]}))
Object.entries(obj).map(([k,v]) => ({[k]:v}))

Solo valores Lodash :

_.valuesSin embargo, el método diseñado para esto es que hay "accesos directos" _.mapy el método de utilidad _.toArrayque también devolvería una matriz que contiene solo los valores del objeto. También podría _.mappensar en _.keysy obtener los valores del objeto utilizando la obj[key]notación.

Nota: _.mapcuando se pasa, un objeto usaría su baseMapcontrolador que está básicamente forEachen las propiedades del objeto.

_.values(obj)
_.map(obj)
_.toArray(obj)
_.map(_.keys(obj), k => obj[k])

Clave y valor de Lodash :

// Outputs an array with [[KEY, VALUE]]
_.entries(obj)
_.toPairs(obj)

// Outputs array with objects containing the keys and values
_.map(_.entries(obj), ([k,v]) => ({[k]:v}))
_.map(_.keys(obj), k => ({[k]: obj[k]}))
_.transform(obj, (r,c,k) => r.push({[k]:c}), [])
_.reduce(obj, (r,c,k) => (r.push({[k]:c}), r), [])

Tenga en cuenta que en los ejemplos anteriores se utiliza ES6 (funciones de flecha y propiedades dinámicas). Puede usar lodash _.fromPairsy otros métodos para componer un objeto si ES6 es un problema.

Akrion
fuente
12

Si desea que la clave (id en este caso) se conserve como una propiedad de cada elemento de la matriz, puede hacerlo

const arr = _(obj) //wrap object so that you can chain lodash methods
            .mapValues((value, id)=>_.merge({}, value, {id})) //attach id to object
            .values() //get the values of the result
            .value() //unwrap array of objects
Sello Mkantjwa
fuente
8

Actualización 2017: Object.values , lodash values y toArray lo hacen. Y para preservar el mapa de teclas y el operador de propagación, juegue bien:

// import { toArray, map } from 'lodash'
const map = _.map

const input = {
  key: {
    value: 'value'
  }
}

const output = map(input, (value, key) => ({
  key,
  ...value
}))

console.log(output)
// >> [{key: 'key', value: 'value'}])
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

Vladimir Chervanev
fuente
7

Transformar objeto en matriz con JavaScript simple ( ECMAScript-2016) Object.values:

var obj = {
    22: {name:"John", id:22, friends:[5,31,55], works:{books:[], films:[]}},
    12: {name:"Ivan", id:12, friends:[2,44,12], works:{books:[], films:[]}}
}

var values = Object.values(obj)

console.log(values);

Si también desea mantener las teclas use Object.entriesy Array#mapasí:

var obj = {
    22: {name:"John", id:22, friends:[5,31,55], works:{books:[], films:[]}},
    12: {name:"Ivan", id:12, friends:[2,44,12], works:{books:[], films:[]}}
}

var values = Object.entries(obj).map(([k, v]) => ({[k]: v}))

console.log(values);

Barba Negra
fuente
5

var arr = _.map(obj)

También puede usar la _.mapfunción (de ambos lodashy underscore) object, manejará internamente ese caso, iterará sobre cada valor y clave con su iterado, y finalmente devolverá una matriz. De hecho, puede usarlo sin iteración (solo _.map(obj)) si solo desea una matriz de valores. Lo bueno es que, si necesita alguna transformación intermedia, puede hacerlo de una vez.

Ejemplo:

Sin embargo, si desea transformar su objeto, puede hacerlo, incluso si necesita preservar la clave, puede hacerlo ( _.map(obj, (v, k) => {...}) con un argumento adicional mapy luego usarlo como desee.

Sin embargo, hay otra solución Vanilla JS para esto (ya que cada lodashsolución debería tener una versión JS pura) como:

  • Object.keysy luego mapa los valores
  • Object.values (en ES-2017)
  • Object.entriesy luego mapcada par clave / valor (en ES-2017)
  • for...in bucle y use cada tecla para fetear valores

Y mucho más. Pero dado que esta pregunta es para lodash(y suponiendo que alguien ya la esté usando), entonces no necesita pensar mucho sobre la versión, el soporte de métodos y el manejo de errores si no se encuentran.

Hay otras soluciones lodash como _.values(más legible para un propósito específico), o obtener pares y luego mapear y así sucesivamente. pero en el caso de que su código necesite flexibilidad para poder actualizarlo en el futuro, ya que necesita preservar keyso transformar un poco los valores, entonces la mejor solución es usar un solo _.mapcomo se indica en esta respuesta. Eso no será tan difícil según la legibilidad también.

Koushik Chatterjee
fuente
2
Agradable, muy simple y muy conciso.
edencorbin
5

Objeto a matriz

De todas las respuestas, creo que esta es la mejor:

let arr = Object.entries(obj).map(([key, val]) => ({ key, ...val }))

que transforma:

{
  a: { p: 1, q: 2},
  b: { p: 3, q: 4}
}

a:

[
  { key: 'a', p: 1, q: 2 }, 
  { key: 'b', p: 3, q: 4 }
]

Matriz a objeto

Para transformar de nuevo:

let obj = arr.reduce((obj, { key, ...val }) => { obj[key] = { ...val }; return obj; }, {})

Para transformar de nuevo manteniendo la clave en el valor:

let obj = arr.reduce((obj, { key, ...val }) => { obj[key] = { key, ...val }; return obj; }, {})

Daré:

{
  a: { key: 'a', p: 1, q: 2 },
  b: { key: 'b', p: 3, q: 4 }
}

Para el último ejemplo, también puede usar lodash _.keyBy(arr, 'key')o _.keyBy(arr, i => i.key).

orad
fuente
3

Si desea una asignación personalizada (como Array.prototype.map original) de Object en una matriz, puede usar _.forEach:

let myObject = {
  key1: "value1",
  key2: "value2",
  // ...
};

let myNewArray = [];

_.forEach(myObject, (value, key) => {
  myNewArray.push({
    someNewKey: key,
    someNewValue: value.toUpperCase() // just an example of new value based on original value
  });
});

// myNewArray => [{ someNewKey: key1, someNewValue: 'VALUE1' }, ... ];

Ver lodashdocumento de _.forEach https://lodash.com/docs/#forEach

Gil Epshtain
fuente