lodash: Array dem Objekt zuordnen


92

Gibt es eine eingebaute Lodash-Funktion, um dies zu übernehmen:

var params = [
    { name: 'foo', input: 'bar' },
    { name: 'baz', input: 'zle' }
];

Und geben Sie Folgendes aus:

var output = {
    foo: 'bar',
    baz: 'zle'
};

Im Moment benutze ich nur Array.prototype.reduce():

function toHash(array, keyName, valueName) {
    return array.reduce(function(dictionary, next) {
        dictionary[next[keyName]] = next[valueName];
        return dictionary;
    }, {});
}

toHash(params, 'name', 'input');

Ich frage mich, ob es eine Abkürzung für Lodash gibt.

Antworten:


137

Ein anderer Weg mit lodash 4.17.2

_.chain(params)
    .keyBy('name')
    .mapValues('input')
    .value();

oder

_.mapValues(_.keyBy(params, 'name'), 'input')

oder mit _.reduce

_.reduce(
    params,
    (acc, { name, input }) => ({ ...acc, [name]: input }),
    {}
)

@Akrikos the _.keyBywandelt das gesamte Array in ein Objekt um, während die Frage hauptsächlich darin besteht, ein Element von jedem Objekt im Array als Schlüssel und ein anderes Element als Wert zu haben. Wenn _.keyByverwendet, sind alle Werte Objekte.
Mustafa Ehsan Alokozay

Danke @MustafaEhsanAlokozay Sie haben Recht, diese Antwort macht nicht genau das Richtige. Ich werde meinen Kommentar löschen, da er nicht hilfreich ist. Das mag Ihren Kommentar seltsam aussehen lassen, aber besser, als wenn mein falscher Kommentar länger wach bleibt.
Akrikos

54

Sie sollten _.keyBy verwenden, um ein Array einfach in ein Objekt zu konvertieren.

Docs hier

Anwendungsbeispiel unten:

var params = [
    { name: 'foo', input: 'bar' },
    { name: 'baz', input: 'zle' }
];
console.log(_.keyBy(params, 'name'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Bei Bedarf können Sie das Array vor der Verwendung von _.keyBy oder das Objekt nach der Verwendung von _.keyBy bearbeiten, um das genau gewünschte Ergebnis zu erhalten.


2
Schauen Sie sich dies zuerst an, um die am häufigsten gewählte Antwort von stasovlas zu verstehen.
Roman Susi

5
Dies ist eine coole Antwort, aber sie beantwortet die Frage NICHT . Die Werte sollten Zeichenfolgen und keine Objekte sein.
Dem Pilafian

34

Ja, es ist hier mit_.reduce

var params = [
    { name: 'foo', input: 'bar' },
    { name: 'baz', input: 'zle' }
];

_.reduce(params , function(obj,param) {
 obj[param.name] = param.input
 return obj;
}, {});

Noch einmal reduce()kommt mit einem anderen Anwendungsfall. Kluge Art, es zu tun!
Dan

Hat jemand die maschinengeschriebene Version davon?
mr.bjerre

Die Realität ist, dass mathematisch gesehen jede Iterationsaktion mit Reduzieren / Injizieren buchstäblich implementiert werden kann, da Reduzieren isomorph zu einer Liste ist. Diese Flexibilität ist jedoch mit einem Preis für die Lesbarkeit verbunden. Verwenden Sie _.reducees nur, wenn dies genau ausdrückt, was Sie tun möchten: In anderen Fällen wird der Punkt des Codes erheblich verdeckt. Ich persönlich bevorzuge die _.zipObjectLösung von @djechlin - andernfalls den _.keyBy/ _.mapValues-Ansatz.
Robert Fischer

16

Dies scheint ein Job für Object.assign zu sein:

const output = Object.assign({}, ...params.map(p => ({[p.name]: p.input})));

Bearbeitet, um als Funktion ähnlich wie OPs zu verpacken, wäre dies:

const toHash = (array, keyName, valueName) => 
    Object.assign({}, ...array.map(o => ({[o[keyName]]: o[valueName]})));

(Danke an Ben Steward, gutes Denken ...)


Schließen Sie dies möglicherweise in eine übergeordnete Funktion ein, damit der Benutzer bestimmen kann, welche Schlüssel verwendet werden sollen, indem er sie übergibt, wie dies beim OP der Fall war.
Ben Steward


10

Dies ist wahrscheinlich ausführlicher als Sie möchten, aber Sie fordern eine etwas komplexe Operation, damit möglicherweise tatsächlicher Code beteiligt ist (der Horror).

Meine Empfehlung, mit zipObjectder das ziemlich logisch ist:

_.zipObject(_.map(params, 'name'), _.map(params, 'input'));

Eine andere Option, hackiger, mit fromPairs:

_.fromPairs(_.map(params, function(val) { return [val['name'], val['input']));

Die anonyme Funktion zeigt die Hackiness - ich glaube nicht, dass JS die Reihenfolge der Elemente in der Objektiteration garantiert, also reicht .values()das Aufrufen nicht aus.


Ich sehe nichts Hackiges an der Verwendung fromPairs, und das Anrufen reicht in der values()Tat nicht aus. Zumindest vom Standpunkt der Lesbarkeit.
X-Yuri

6

Ein anderer Weg mit lodash

Paare erstellen und dann entweder ein Objekt erstellen oder ES6 Mapeinfach

_(params).map(v=>[v.name, v.input]).fromPairs().value()

oder

_.fromPairs(params.map(v=>[v.name, v.input]))

Hier ist ein Arbeitsbeispiel


1
Der gute Teil dieser Lösung ist, dass sie auch in einfachem ES möglich ist:Object.fromEntries(params.map(v => [v.name, v.input]))
fregante

@fregante, Chrome 73+ nur caniuse.com/?search=fromEntries
d9k

6

Es kann auch ohne Verwendung einer Lodash-Funktion wie dieser gelöst werden:

let paramsVal = [
    { name: 'foo', input: 'bar' },
    { name: 'baz', input: 'zle' }
];
let output = {};

paramsVal.forEach(({name, input})=>{
  output[name] = input;
})


console.log(output);

Geben Sie hier die Bildbeschreibung ein

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.