Ruby memiliki metode pembantu untuk Hash yang memungkinkan Anda memperlakukan Hash seolah-olah itu terbalik (pada dasarnya, dengan membiarkan Anda mengakses kunci melalui nilai-nilai):
{a: 1, b: 2, c: 3}.key(1)
=> :a
Jika Anda ingin menyimpan hash terbalik, maka Hash # invert harus berfungsi untuk sebagian besar situasi:
{a: 1, b: 2, c: 3}.invert
=> {1=>:a, 2=>:b, 3=>:c}
TAPI...
Jika Anda memiliki nilai duplikat, invert
akan membuang semua kecuali kemunculan nilai terakhir Anda (karena itu akan terus mengganti nilai baru untuk kunci itu selama iterasi). Demikian juga, key
hanya akan mengembalikan pertandingan pertama:
{a: 1, b: 2, c: 2}.key(2)
=> :b
{a: 1, b: 2, c: 2}.invert
=> {1=>:a, 2=>:c}
Jadi, jika nilai Anda unik, Anda dapat menggunakannya Hash#invert
. Jika tidak, maka Anda dapat menyimpan semua nilai sebagai array, seperti ini:
class Hash
# like invert but not lossy
# {"one"=>1,"two"=>2, "1"=>1, "2"=>2}.inverse => {1=>["one", "1"], 2=>["two", "2"]}
def safe_invert
each_with_object({}) do |(key,value),out|
out[value] ||= []
out[value] << key
end
end
end
Catatan: Kode dengan tes ini sekarang ada di GitHub .
Atau:
class Hash
def safe_invert
self.each_with_object({}){|(k,v),o|(o[v]||=[])<<k}
end
end
each_with_object
lebih masuk akal di sini daripadainject
.each_with_object({}){ |i,o|k,v = *i; o[v] ||=[]; o[v] << k}
... bagusAnda bertaruh ada satu! Selalu ada cara yang lebih singkat untuk melakukan sesuatu di Ruby!
Ini sangat sederhana, cukup gunakan
Hash#invert
:Dan lagi!
sumber
Ini akan menangani nilai duplikat juga.
sumber
Hash#inverse
Memberi anda:sedangkan
invert
metode bawaan hanya rusak:sumber
Menggunakan Array
Menggunakan Hash
sumber
Jika Anda memiliki hash di mana kuncinya unik, Anda dapat menggunakan Hash # invert :
Namun, itu tidak akan berhasil jika Anda memiliki kunci yang tidak unik, di mana hanya kunci terakhir yang terlihat yang akan disimpan:
Jika Anda memiliki hash dengan kunci tidak unik, Anda dapat melakukannya:
Jika nilai hash sudah array, Anda bisa melakukan:
sumber