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.

Ader
quelle

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 }),
    {}
)
stasovlas
quelle
@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.

danday74
quelle
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;
}, {});
Jagdish Idhate
quelle
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 ...)

RainedColony
quelle
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
11

Sie können einzeiliges Javascript mit Array-Reduktionsmethode und ES6-Destrukturierung verwenden , um ein Array von Schlüsselwertpaaren in ein Objekt zu konvertieren.

arr.reduce((map, { name, input }) => ({ ...map, [name]: input }), {});
Faisal Hasnain
quelle
3
Leider ist dies O (n ^ 2).
Jimrandomh
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.

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

Koushik Chatterjee
quelle
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

Zeeshan Afzal Satti
quelle