Objekt mit lodash in Array umwandeln

164

Wie kann ich eine große Transformation objectzu arraymit 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
quelle
@Mritunjay Ja, weil die Dokumente einen so guten Überblick über die Bibliothek haben ... nicht. Es ist nur eine erschöpfende Liste von Funktionen, und das Durchlaufen jeder einzelnen Funktion könnte sich als Zeitverschwendung erweisen, wenn es keine gibt. Die Frage ist fair.
Epirocks

Antworten:

260

Du kannst tun

var arr = _.values(obj);

Dokumentation finden Sie hier.

Daniel Schmidt
quelle
34
Was ist, wenn Sie den Schlüssel als Eigenschaft erhalten möchten? (In diesem Beispiel, wenn die idEigenschaft nicht vorhanden war und Sie sie basierend auf dem Schlüssel jedes Objekts erstellen wollten.
Michael Liquori
8
Sie könnten so etwas tun:var arr = _.values(_.mapKeys(obj, function(value, key) { value.id = key; return value; }));
Daniel Schmidt
1
@ DanielSchmidt Ich bin nicht sicher, was ich falsch gemacht habe, aber dieses Beispiel hat nur 1 Zeile für mich zurückgegeben. :( Also habe ich den returnWert manuell auf ein Array wie dieses const divisionsList = []; _.mapKeys(divisions, (value, key) => { divisionsList[key] = value; });
verschoben
8
@ JohnnyQ Ich denke, Sie müssen stattdessen mapValues ​​verwenden, zBconst toArrayWithKey = (obj, keyAs) => _.values(_.mapValues(obj, (value, key) => { value[keyAs] = key; return value; }));
Orjan
1
@orjan Ja, ich habe das tatsächlich herausgefunden, nur vergessen zu aktualisieren. Danke für das.
JohnnyQ
38
_.toArray(obj);

Ausgaben als:

[
  {
    "name": "Ivan",
    "id": 12,
    "friends": [
      2,
      44,
      12
    ],
    "works": {
      "books": [],
      "films": []
    }
  },
  {
    "name": "John",
    "id": 22,
    "friends": [
      5,
      31,
      55
    ],
    "works": {
      "books": [],
      "films": []
    }
  }
]"
Jivings
quelle
1
_.toArray () Funktioniert gut @jivings
Syed Zain Ali
4
Um nur Werte toArrayzu erhalten, ist dies eine gute Option, aber es gibt keine Möglichkeit, die Schlüssel bei Bedarf beizubehalten.
Koushik Chatterjee
33

Eine moderne native Lösung, wenn jemand interessiert ist:

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

oder (nicht IE):

const arr = Object.entries(obj).map(([key, value]) => ({ key, value }));
Dominic
quelle
2
warum nicht einfachObject.keys(obj).map(key=>({key,value: obj[key]}))
Koushik Chatterjee
1
Ich mag es, dass es nicht einmal User Lodash gibt, gut gemacht, Sir!
HungryPipo
1
@Dominic Jetzt haben Sie Ihre vollständige Antwort geändert und sie auch ohne Erwähnung aus meinem Kommentar übernommen (Sie haben das herausgeschnitten). Gut gemacht 👏 😁😁
Koushik Chatterjee
1
@KoushikChatterjee fügte es wieder hinzu
Dominic
2
Wäre das hilfreicher? const arr = Object.keys(obj).map(id => ({ id, ...obj[id] })); Dies würde das gesamte Objekt in die zurückgegebenen Daten bringen, nein? (mit 'id', da der ursprüngliche Fragesteller seinen Schlüssel als ID-Requisite speichern wollte)
zabaat
20

Für mich hat das funktioniert:

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

Es wendet sich

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

in

[{"a":"b"}, {"c":"d"}, {"e":"f"}]
NoNine
quelle
1
Ich musste ein Objekt in ein Array umwandeln, so dass jeder Schlüssel / Wert des ursprünglichen Objekts ein {key: value} -Objekt im Array ist. _.toPairs (Daten) nimmt das Objekt {"a": "b", "c": "d", "e": "f"} und gibt es als Array von Arrays wie [["a": "zurück. b "], [" c ":" d "], [" e ":" f "]]. _.fromPairs macht das Gegenteil, es nimmt ein Array mit 2 Elementen: ["a", "b"] und gibt es als Objekt zurück: {"a": "b"}. Mit _.map habe ich das Array durchlaufen, wenn Arrays von _.toPairs erstellt wurden, um es mithilfe von _.fromPairs in ein Array von Objekten umzuwandeln.
NoNine
1
Ich bin froh, dass ich nach unten gescrollt habe, um dies zu sehen. Ihre Lösung hat bei mir funktioniert! Vielen Dank!
Wale
@NoNine Sie müssen keine Map auf ein Array (von Array) anwenden, sondern können sie direkt auf das Eingabeobjekt anwenden und jedes Schlüsselwertpaar zurückgeben. Weitere Informationen finden Sie in _.map(data, (v,k)=>({[k]: v}))meiner Antwort. _.toPairsund _fromPairsist hier zusätzlich und unnötig.
Koushik Chatterjee
Dafür ist die Frage nicht gedacht. weil es etwas schwierig ist, das Ergebnis zu verwenden, da jeder Eintrag einen Schlüssel enthält (den Sie nicht kennen) und Sie für jeden einzelnen Eintrag eine Logik (z. B. Object.keys oder Object.values) durchlaufen müssen, um den Wert von zu erhalten Wenn Spielzeug die Schlüssel erhalten möchte, können Sie eine Reihe von Objekten erstellen, die wie [{key: 'someKey', val: 'The value'}, {....},...]
folgt
13

Es gibt viele Möglichkeiten, um das gewünschte Ergebnis zu erzielen. Teilen wir sie in Kategorien ein:

Nur ES6-Werte :

Hauptmethode hierfür ist Object.values . Mit Object.keys und Array.map können Sie jedoch auch das erwartete Ergebnis erzielen :

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

ES6 Schlüssel & Wert :

Mithilfe der dynamischen / berechneten Eigenschaften und der Destrukturierung von Map und ES6 können Sie den Schlüssel beibehalten und ein Objekt von der Map zurückgeben.

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

Nur Lodash-Werte :

Die dafür entwickelte Methode ist _.valuesjedoch, dass es "Verknüpfungen" wie gibt_.map und die Utility-Methode gibt, _.toArraydie auch ein Array zurückgeben würde, das nur die Werte vom Objekt enthält. Man könnte auch _.mapwenn die _.keysund die Werte aus dem Objekt erhalten , indem die Verwendung von obj[key]Notation.

Hinweis: _.mapWenn ein Objekt übergeben wird, wird es verwendetbaseMap Handler, der sich im Wesentlichen forEachauf den Objekteigenschaften befindet.

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

Lodash Key & Value :

// 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), [])

Beachten Sie, dass in den obigen Beispielen ES6 verwendet wird (Pfeilfunktionen und dynamische Eigenschaften). Sie können lodash verwenden_.fromPairs und andere Methoden verwenden, um ein Objekt zu , wenn ES6 ein Problem darstellt.

Akrion
quelle
12

Wenn Sie möchten, dass der Schlüssel (in diesem Fall die ID) als Eigenschaft jedes Array-Elements erhalten bleibt, können Sie dies tun

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
quelle
8

Update 2017: Object.values , lodash values und toArray machen es. Und Schlüssel zu bewahren Karte und Verbreitung Betreiber Spiel schön:

// 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
quelle
7

Transformieren eines Objekts in ein Array mit einfachem JavaScript ( 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);

Wenn Sie auch die Schlüssel verwenden möchten Object.entriesund dies Array#mapmögen:

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
quelle
5

var arr = _.map(obj)

Sie können auch die _.mapFunktion (von beiden lodashund underscore) verwenden object. Sie behandelt diesen Fall intern, iteriert mit Ihrem Iterat über jeden Wert und Schlüssel und gibt schließlich ein Array zurück. Tatsächlich können Sie es ohne Iteration (nur _.map(obj)) verwenden, wenn Sie nur ein Array von Werten möchten. Der gute Teil ist, dass Sie, wenn Sie eine Transformation dazwischen benötigen, dies auf einmal tun können.

Beispiel:

Wenn Sie Ihr Objekt jedoch transformieren möchten, können Sie dies tun, auch wenn Sie den Schlüssel beibehalten müssen. Sie können dies ( _.map(obj, (v, k) => {...}) mit einem zusätzlichen Argument tun mapund es dann verwenden, wie Sie möchten.

Es gibt jedoch andere Vanilla JS-Lösungen dafür (da jede lodashLösung eine reine JS-Version davon haben sollte) wie:

  • Object.keysund dann mapsie zu Werten
  • Object.values (in ES-2017)
  • Object.entriesund dann mapjedes Schlüssel / Wert-Paar (in ES-2017)
  • for...in Schleife und verwenden Sie jede Taste zum Abrufen von Werten

Und vieles mehr. Da diese Frage jedoch für lodash(und vorausgesetzt, jemand verwendet sie bereits) gilt, müssen Sie nicht viel über die Version, die Unterstützung von Methoden und die Fehlerbehandlung nachdenken, wenn diese nicht gefunden werden.

Es gibt andere Lodash-Lösungen wie _.values(für bestimmte Zwecke besser lesbar) oder Paare abrufen und dann zuordnen und so weiter. Für den Fall, dass Ihr Code flexibel sein muss, damit Sie ihn in Zukunft aktualisieren können, da Sie keysWerte ein wenig beibehalten oder transformieren müssen, ist die beste Lösung, einen einzelnen _.mapCode als Adresse in dieser Antwort zu verwenden. Das wird auch in Bezug auf die Lesbarkeit nicht so schwierig sein.

Koushik Chatterjee
quelle
2
Schön, sehr einfach und sehr prägnant.
Edencorbin
5

Objekt zum Array

Von allen Antworten halte ich diese für die beste:

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

das verwandelt:

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

zu:

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

Array zu Objekt

Um sich zurück zu verwandeln:

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

So transformieren Sie zurück und behalten den Schlüssel im Wert:

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

Wird geben:

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

Für das letzte Beispiel können Sie auch lodash _.keyBy(arr, 'key')oder verwenden _.keyBy(arr, i => i.key).

orad
quelle
3

Wenn Sie eine benutzerdefinierte Zuordnung (wie die ursprüngliche Array.prototype.map) von Object zu einem Array wünschen, können Sie einfach Folgendes verwenden _.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' }, ... ];

Siehe lodashDokument von _.forEach https://lodash.com/docs/#forEach

Gil Epshtain
quelle