Oke jadi ini masalahnya, saya sudah lama mencari di Google untuk menemukan solusi untuk ini dan meskipun ada banyak di luar sana, mereka sepertinya tidak melakukan pekerjaan yang saya cari.
Pada dasarnya saya memiliki array yang terstruktur seperti ini
["item 1", "item 2", "item 3", "item 4"]
Saya ingin mengonversi ini menjadi Hash sehingga terlihat seperti ini
{ "item 1" => "item 2", "item 3" => "item 4" }
yaitu item yang ada di indeks 'genap' adalah kunci dan item pada indeks 'aneh' adalah nilainya.
Ada ide bagaimana melakukan ini dengan bersih? Saya kira metode brute force adalah dengan hanya menarik semua indeks genap ke dalam array yang terpisah dan kemudian loop di sekitarnya untuk menambahkan nilai-nilai.
*
disebut operator percikan . Dibutuhkan array dan mengonversinya menjadi daftar item literal. Jadi*[1,2,3,4]
=>1, 2, 3, 4
. Dalam contoh ini, hal di atas setara dengan melakukanHash["item 1", "item 2", "item 3", "item 4"]
. DanHash
memiliki[]
metode yang menerima daftar argumen (membuat bahkan indeks kunci dan nilai indeks ganjil), tetapiHash[]
tidak menerima array, jadi kami memercikkan array menggunakan*
.Hash[a.each_slice(2).to_a]
.Ruby 2.1.0 memperkenalkan
to_h
metode pada Array yang melakukan apa yang Anda butuhkan jika array asli Anda terdiri dari array pasangan nilai kunci: http://www.ruby-doc.org/core-2.1.0/Array.html#method -i-to_h .sumber
bar
harus simbol, dan simbol:2
harus bilangan bulat. Jadi, ekspresi Anda dikoreksi adalaha = [[:foo, 1], [:bar, 2]]
).Cukup gunakan
Hash.[]
dengan nilai-nilai dalam array. Sebagai contoh:sumber
*arr
mengkonversiarr
ke daftar argumen, jadi ini memanggil[]
metode Hash dengan isi arr sebagai argumen.Atau jika Anda memiliki array
[key, value]
array, Anda dapat melakukan:sumber
Hash[*arr]
{ [1, 2] => [3, 4] }
. Dan karena judul pertanyaannya berbunyi "Array to Hash" dan metode "Hash to Array" bawaan:,{ 1 => 2, 3 => 4}.to_a # => [[1, 2], [3, 4]]
saya pikir lebih dari satu yang bisa berakhir di sini mencoba mendapatkan kebalikan dari metode "Hash to Array" bawaan. Sebenarnya, begitulah akhirnya saya berakhir di sini.Hash[arr]
akan melakukan pekerjaan untuk Anda.#inject
metode. Dengan#merge!
,#each_with_object
seharusnya sudah digunakan. Jika#inject
bersikeras,#merge
daripada#merge!
seharusnya digunakan.Ini yang saya cari saat mencari di Google:
[{a: 1}, {b: 2}].reduce({}) { |h, v| h.merge v } => {:a=>1, :b=>2}
sumber
merge
, itu membangun dan membuang iterasi per loop baru dan sangat lambat. Jika Anda memiliki array hash, cobalah[{a:1},{b:2}].reduce({}, :merge!)
- menggabungkan semuanya menjadi hash (baru) yang sama..reduce(&:merge!)
[{a: 1}, {b: 2}].reduce(&:merge!)
mengevaluasi ke{:a=>1, :b=>2}
[{a: 1}, {b: 2}].reduce(&:merge!)
adalah sama dengan[{a: 1}, {b: 2}].reduce { |m, x| m.merge(x) }
yang sama dengan[{b: 2}].reduce({a: 1}) { |m, x| m.merge(x) }
.Enumerator
termasukEnumerable
. Karena2.1
,Enumerable
juga punya metode#to_h
. Itu sebabnya, kita dapat menulis: -Karena
#each_slice
tanpa blok memberi kitaEnumerator
, dan sesuai penjelasan di atas, kita dapat memanggil#to_h
metode padaEnumerator
objek.sumber
Anda dapat mencoba seperti ini, untuk array tunggal
untuk array array
sumber
atau, jika Anda membenci
Hash[ ... ]
:atau, jika Anda adalah penggemar malas pemrograman fungsional yang rusak:
sumber
Hash[ ... ]
tetapi ingin menggunakannya sebagai metode dirantai (seperti yang dapat Anda lakukan denganto_h
) Anda dapat menggabungkan saran Boris dan menulis:arr.each_slice( 2 ).map { |e| e }.tap { |a| break Hash[a] }
Semua jawaban menganggap array awal adalah unik. OP tidak menentukan cara menangani array dengan entri duplikat, yang menghasilkan kunci duplikat.
Mari lihat:
Anda akan kehilangan
item 1 => item 2
pasangan karena ditimpa olehitem 1 => item 5
:Semua metode, termasuk
reduce(&:merge!)
hasil dalam penghapusan yang sama.Bisa jadi ini persis seperti yang Anda harapkan. Namun dalam kasus lain, Anda mungkin ingin mendapatkan hasil dengan
Array
nilai for gantinya:Cara naif adalah membuat variabel pembantu, hash yang memiliki nilai default, dan kemudian mengisinya dalam satu lingkaran:
Mungkin bisa digunakan
assoc
danreduce
dilakukan di atas dalam satu baris, tetapi itu menjadi lebih sulit untuk dipikirkan dan dibaca.sumber