transformer l'objet en tableau avec lodash

165

Comment puis-je transformer un gros objecten arrayavec 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
la source
@Mritunjay Oui parce que les documents ont une très bonne vue d'ensemble de la bibliothèque ... non. C'est juste une liste exhaustive de fonctions et passer par chacune d'elles pourrait bien s'avérer une perte de temps s'il n'y en a pas. La question est juste.
Epirocks

Réponses:

265

Tu peux faire

var arr = _.values(obj);

Pour la documentation, voir ici.

Daniel Schmidt
la source
34
Et si vous vouliez conserver la clé en tant que propriété? (dans cet exemple, si la idpropriété n'existait pas et que vous vouliez la créer en fonction de la clé de chaque objet.
Michael Liquori
8
Vous pourriez faire quelque chose comme ceci:var arr = _.values(_.mapKeys(obj, function(value, key) { value.id = key; return value; }));
Daniel Schmidt
1
@DanielSchmidt Je ne suis pas sûr de ce que j'ai mal fait, mais cet échantillon n'a renvoyé qu'une ligne pour moi. :( Donc, ce que j'ai fait, c'est pousser manuellement la returnvaleur dans un tableau comme celui-ci: const divisionsList = []; _.mapKeys(divisions, (value, key) => { divisionsList[key] = value; });j'apprécierais tous les commentaires ou suggestions pour améliorer cette approche.
JohnnyQ
8
@JohnnyQ Je pense que vous devrez utiliser mapValues ​​à la place, par exempleconst toArrayWithKey = (obj, keyAs) => _.values(_.mapValues(obj, (value, key) => { value[keyAs] = key; return value; }));
orjan
1
@orjan Oui, j'ai compris cela, j'ai juste oublié de mettre à jour. Merci pour ça.
JohnnyQ
38
_.toArray(obj);

Sorties comme:

[
  {
    "name": "Ivan",
    "id": 12,
    "friends": [
      2,
      44,
      12
    ],
    "works": {
      "books": [],
      "films": []
    }
  },
  {
    "name": "John",
    "id": 22,
    "friends": [
      5,
      31,
      55
    ],
    "works": {
      "books": [],
      "films": []
    }
  }
]"
Jivings
la source
1
_.toArray () Fonctionne très bien @jivings
Syed Zain Ali
4
pour obtenir uniquement des valeurs, c'est une bonne option, mais toArrayil n'y a aucun moyen de conserver les clés si nécessaire.
Koushik Chatterjee
33

Une solution native moderne si quelqu'un est intéressé:

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

ou (pas IE):

const arr = Object.entries(obj).map(([key, value]) => ({ key, value }));
Dominique
la source
2
pourquoi pas justeObject.keys(obj).map(key=>({key,value: obj[key]}))
Koushik Chatterjee
1
J'aime le fait qu'il n'utilise même pas le lodash, bravo monsieur!
HungryPipo
1
@Dominic Maintenant, vous avez changé votre réponse complète et l'avez tirée de mon commentaire, même sans mention (vous l'avez supprimée). Bien joué 👏 😁😁
Koushik Chatterjee
1
@KoushikChatterjee l'a ajouté à nouveau
Dominic
2
Serait-ce plus utile? const arr = Object.keys(obj).map(id => ({ id, ...obj[id] })); cela amènerait l'objet entier dans les données renvoyées non? (en utilisant 'id' puisque le demandeur d'origine voulait stocker sa clé comme accessoire d'identité)
zabaat
20

Pour moi, cela a fonctionné:

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

Ça tourne

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

dans

[{"a":"b"}, {"c":"d"}, {"e":"f"}]
NoNine
la source
1
J'avais besoin de transformer un objet en un tableau, de manière à ce que chaque clé / valeur de l'objet d'origine soit un objet {clé: valeur} dans le tableau. _.toPairs (data) prend l'objet {"a": "b", "c": "d", "e": "f"} et le renvoie comme un tableau de tableaux comme [["a": " b "], [" c ":" d "], [" e ":" f "]]. _.fromPairs fait l'inverse, il prend un tableau avec 2 éléments: ["a", "b"] et le renvoie comme un objet: {"a": "b"}. En utilisant _.map, j'ai parcouru le tableau if des tableaux créés par _.toPairs pour le transformer en un tableau d'objets à l'aide de _.fromPairs.
NoNine
1
Je suis content d'avoir fait défiler vers le bas pour voir ceci. Votre solution a fonctionné pour moi! Merci!
Wale
@NoNine Vous n'avez pas besoin d'appliquer la carte sur un tableau (de tableau), vous pouvez l'appliquer directement sur l'objet d'entrée et renvoyer chaque paire clé / valeur _.map(data, (v,k)=>({[k]: v}))voir ma réponse pour plus de détails. _.toPairset _fromPairsest supplémentaire et inutile ici.
Koushik Chatterjee
Ce n'est pas à cela que vise la question. car il est un peu difficile d'utiliser le résultat car chaque entrée contient une clé (que vous ne connaissez pas) et encore une fois, vous devez passer par une logique (par exemple, Object.keys ou Object.values) pour chaque entrée séparée pour obtenir la valeur de chacun, si le jouet veut conserver les clés, vous pouvez créer un tableau d'objets structurés comme[{key: 'someKey', val: 'The value'}, {....},...]
Koushik Chatterjee
13

Il existe plusieurs façons d'obtenir le résultat que vous recherchez. Permet de les diviser en catégories:

Valeurs ES6 uniquement :

La méthode principale pour cela est Object.values . Mais en utilisant Object.keys et Array.map, vous pouvez également obtenir le résultat attendu:

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

Clé et valeur ES6 :

En utilisant la carte et les propriétés dynamiques / calculées ES6 et la déstructuration, vous pouvez conserver la clé et renvoyer un objet à partir de la carte.

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

Valeurs Lodash uniquement :

La méthode conçue pour cela est _.valuescependant qu'il existe des "raccourcis" comme _.mapet la méthode utilitaire _.toArrayqui renverrait également un tableau contenant uniquement les valeurs de l'objet. Vous pouvez également utiliser _.maple _.keyset obtenir les valeurs de l'objet en utilisant la obj[key]notation.

Remarque: une _.mapfois passé, un objet utilise son baseMapgestionnaire qui est essentiellement forEachsur les propriétés de l'objet.

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

Clé et valeur 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), [])

Notez que dans les exemples ci-dessus, ES6 est utilisé (fonctions fléchées et propriétés dynamiques). Vous pouvez utiliser lodash _.fromPairset d'autres méthodes pour composer un objet si ES6 est un problème.

Akrion
la source
12

Si vous voulez que la clé (id dans ce cas) soit préservée en tant que propriété de chaque élément du tableau, vous pouvez le faire

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
la source
8

Mise à jour 2017: Object.values , lodash values et toArray le font. Et pour conserver la carte des touches et répartir l'opérateur, jouez 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
la source
7

Transformer un objet en tableau avec du JavaScript brut ( 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 vous souhaitez également conserver les clés, utilisez Object.entrieset Array#mapcomme ceci:

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);

BlackBeard
la source
5

var arr = _.map(obj)

Vous pouvez également utiliser la _.mapfonction (des deux lodashet underscore) avec object, elle gérera ce cas en interne, itérera sur chaque valeur et clé avec votre iteratee, et finalement retournera un tableau. En fait, vous pouvez l'utiliser sans aucune itération (juste _.map(obj)) si vous voulez juste un tableau de valeurs. L'avantage est que si vous avez besoin d'une transformation entre les deux, vous pouvez le faire en une seule fois.

Exemple:

Cependant, si vous souhaitez transformer votre objet, vous pouvez le faire, même si vous devez conserver la clé, vous pouvez le faire ( _.map(obj, (v, k) => {...}) avec un argument supplémentaire dans map, puis l'utiliser comme vous le souhaitez.

Cependant, il existe d'autres solutions Vanilla JS à cela (comme chaque lodashsolution devrait en être une version JS pure) comme:

  • Object.keyset puis maples valeurs
  • Object.values (dans ES-2017)
  • Object.entriespuis mapchaque paire clé / valeur (dans ES-2017)
  • for...in boucle et utilise chaque clé pour feting des valeurs

Et beaucoup plus. Mais comme cette question est pour lodash(et en supposant que quelqu'un l'utilise déjà), vous n'avez pas besoin de beaucoup penser à la version, au support des méthodes et à la gestion des erreurs si celles-ci ne sont pas trouvées.

Il existe d'autres solutions de lodash comme _.values(plus lisibles pour un objectif spécifique), ou obtenir des paires, puis une carte, etc. mais dans le cas où votre code a besoin de flexibilité pour que vous puissiez le mettre à jour à l'avenir car vous devez conserver keysou transformer un peu les valeurs, la meilleure solution est d'en utiliser un _.mapcomme indiqué dans cette réponse. Ce ne sera pas si difficile en termes de lisibilité également.

Koushik Chatterjee
la source
2
Nice, très simple et très concis.
edencorbin
5

Objet à tableau

De toutes les réponses, je pense que celle-ci est la meilleure:

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

qui transforme:

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

à:

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

Tableau à objet

Pour reconstituer:

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

Pour reconstituer en gardant la clé dans la valeur:

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

Va donner:

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

Pour le dernier exemple, vous pouvez également utiliser lodash _.keyBy(arr, 'key')ou _.keyBy(arr, i => i.key).

orad
la source
3

Si vous souhaitez un mappage personnalisé (comme Array.prototype.map original) d'Object dans un Array, vous pouvez simplement utiliser _.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' }, ... ];

Voir lodashdoc de _.forEach https://lodash.com/docs/#forEach

Gil Epshtain
la source