lodash: memetakan larik ke objek


91

Apakah ada fungsi lodash bawaan untuk melakukan ini:

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

Dan keluaran ini:

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

Saat ini saya hanya menggunakan 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');

Ingin tahu apakah ada jalan pintas lodash.

Jawaban:


133

Cara lain dengan lodash 4.17.2

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

atau

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

atau dengan _.reduce

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

@ Akrikos the _.keyByakan mengubah seluruh array menjadi sebuah objek, sedangkan pertanyaannya sebagian besar tentang memiliki satu item dari setiap objek dalam array sebagai kunci dan satu item lainnya sebagai nilainya. Jika _.keyBydigunakan, maka semua nilai akan menjadi objek.
Mustafa Ehsan Alokozay

Terima kasih @MustafaEhsanAlokozay Anda benar, jawaban itu tidak tepat. Saya akan menghapus komentar saya karena tidak membantu. Itu mungkin membuat komentar Anda terlihat aneh, tetapi lebih baik daripada komentar saya yang salah bertahan lebih lama.
Akrikos

53

Anda harus menggunakan _.keyBy untuk mengonversi larik menjadi objek dengan mudah.

Dokumen di sini

Contoh penggunaan di bawah ini:

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>

Jika diperlukan, Anda dapat memanipulasi array sebelum menggunakan _.keyBy atau objek setelah menggunakan _.keyBy untuk mendapatkan hasil yang diinginkan.


2
Lihat pertama ini untuk memahami jawaban yang paling banyak dipilih oleh stasovlas.
Roman Susi

3
Ini adalah jawaban yang keren, tetapi TIDAK menjawab pertanyaannya. Nilainya harus berupa string, bukan objek.
Dem Pilafian

34

Ya di sini , menggunakan_.reduce

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

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

Sekali lagi reduce()masuk dengan kasus penggunaan lain. Cara cerdas melakukannya!
Dan

Adakah yang punya versi ketikan ini?
mr.bjerre

Kenyataannya adalah benar secara matematis bahwa Anda dapat mengimplementasikan secara harfiah tindakan iterasi apa pun menggunakan reduce / inject, karena mengurangi isomorfik ke daftar. Namun, fleksibilitas itu datang dengan harga dalam keterbacaan. Jangan gunakan _.reducekecuali jika itu secara akurat mengungkapkan apa yang Anda coba lakukan: itu secara signifikan mengaburkan inti kode dalam kasus lain. Saya pribadi lebih suka _.zipObjectsolusi oleh @djechlin - jika gagal, pendekatan _.keyBy/ _.mapValues.
Robert Fischer

16

Ini sepertinya pekerjaan untuk Object.assign:

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

Diedit untuk membungkus sebagai fungsi yang mirip dengan OP, ini akan menjadi:

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

(Terima kasih kepada Ben Steward, pemikiran yang bagus ...)


Mungkin membungkusnya dalam fungsi induk sehingga pengguna dapat menentukan kunci apa yang akan digunakan dengan melewatkannya, seperti yang dimiliki OP.
Ben Steward


10

Ini mungkin lebih bertele-tele dari yang Anda inginkan, tetapi Anda meminta operasi yang sedikit rumit sehingga kode sebenarnya mungkin terlibat (ngeri).

Rekomendasi saya, dengan zipObjectitu cukup logis:

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

Opsi lain, lebih hacky, menggunakan fromPairs:

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

Fungsi anonim menunjukkan peretasan - Saya tidak percaya JS menjamin urutan elemen dalam iterasi objek, jadi pemanggilan .values()tidak akan berhasil.


Saya tidak melihat ada yang tidak sopan tentang penggunaan fromPairs, dan panggilan values()memang tidak akan berhasil. Setidaknya dari sudut pandang keterbacaan.
x-yuri

6

Cara lain dengan lodash

membuat pasangan, dan kemudian membuat objek atau ES6 Mapdengan mudah

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

atau

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

Berikut adalah contoh yang berfungsi


1
Bagian yang baik dari solusi ini adalah bahwa itu juga layak di ES biasa:Object.fromEntries(params.map(v => [v.name, v.input]))
fregante

@fregante, Chrome 73+ hanya caniuse.com/?search=fromEntries
D9k

6

Itu juga bisa diselesaikan tanpa menggunakan fungsi lodash apa pun seperti ini:

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

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


console.log(output);

masukkan deskripsi gambar di sini

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.