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.

inti
sumber

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

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

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

Anda dapat menggunakan satu liner javascript dengan metode pengurangan array dan ES6 merusak untuk mengonversi array pasangan nilai kunci menjadi objek.

arr.reduce((map, { name, input }) => ({ ...map, [name]: input }), {});
Faisal Hasnain
sumber
3
Sayangnya, ini adalah O (n ^ 2).
jimrandomh
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.

djechlin.dll
sumber
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

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

Zeeshan Afzal Satti
sumber