2010-09-25 88 views
153

鑑於我有下面的客戶端散列,有沒有一種快速的紅寶石方式(無需編寫多行腳本)來獲得我想匹配的密鑰CLIENT_ID?例如。如何獲得client_id == "2180"的鑰匙?如何找到一個包含匹配值的散列鍵

clients = { 
    "yellow"=>{"client_id"=>"2178"}, 
    "orange"=>{"client_id"=>"2180"}, 
    "red"=>{"client_id"=>"2179"}, 
    "blue"=>{"client_id"=>"2181"} 
} 

回答

144

你可以使用Enumerable#select

clients.select{|key, hash| hash["client_id"] == "2180" } 
#=> [["orange", {"client_id"=>"2180"}]] 

注意,結果將是所有匹配的值,其中每一個鍵和值的數組的數組。

+0

This works too! – Coderama

+18

@Coderama find和select之間的區別在於find返回第一個匹配select返回全部匹配。 –

+0

我明白了,所以對於有多個匹配的情況,這將是更安全的選擇。 – Coderama

9

試試這個:

clients.find{|key,value| value["client_id"] == "2178"}.first 
+1

這很有用 – Coderama

+4

如果find返回nil,則會引發異常,因爲您無法在nil上調用.first。 – Schrockwell

+1

如果使用Rails,你可以使用'.try(:first)'而不是'.first'來避免異常(如果你期望值可能會丟失)。 –

323

Ruby 1.9的和更大:

hash.key(value) => key 

紅寶石1.8

你可以使用hash.index

hsh.index(value) => key

返回給定值的關鍵字。如果找不到 ,則返回nil

h = { "a" => 100, "b" => 200 }
h.index(200) #=> "b"
h.index(999) #=> nil

因此,要獲得"orange",你可以只使用:

clients.key({"client_id" => "2180"}) 
+1

我得到零當我運行此... – Coderama

+0

@Coderama我不::http://codepad.org/2JpX9ei5 – Aillyn

+2

如果哈希有多個鍵,這將會有點混亂,因爲你需要給整個哈希到'索引'。 –

46

可以顛倒散。 clients.invert["client_id"=>"2180"]回報"orange"

+3

這也看起來像一個聰明的方式(因爲它很短)來做到這一點! – Coderama

+0

這是我需要的形式數組(對於選擇框),它創建一個向後散列 –

21

你可以使用hashname.key(VALUENAME)

或者反轉可能是爲了。 new_hash = hashname.invert會給你一個new_hash,讓你更傳統地做事情。

+3

這是在Ruby的最新版本(1.9+)中執行它的正確方法。 –

+0

'#invert'在這種情況下是一個非常糟糕的主意,因爲你基本上是爲了找到一個關鍵字而爲拋棄哈希對象分配內存。取決於散列大小,它會對性能產生嚴重影響 –

3

從文檔:

  • (?對象)檢測(ifnone =無){| OBJ | ...}
  • (Object?)find(ifnone = nil){| obj | ...}
  • (對象)檢測(ifnone =無)
  • (對象)找到(ifnone =無)

通行證枚舉到塊中的每個條目。返回第一個塊不是假的。如果沒有對象匹配,則調用ifnone並在指定時返回結果,否則返回nil。

如果未指定塊,則返回枚舉數。

(1..10).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> nil 
(1..100).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> 35 

這爲我工作:

clients.detect{|client| client.last['client_id'] == '2180' } #=> ["orange", {"client_id"=>"2180"}] 

clients.detect{|client| client.last['client_id'] == '999999' } #=> nil 

參見: http://rubydoc.info/stdlib/core/1.9.2/Enumerable#find-instance_method

0

找到一個特定值的關鍵,最好的辦法是使用可用於散列關鍵字的方法。 ...

gender = {"MALE" => 1, "FEMALE" => 2} 
gender.key(1) #=> MALE 

我希望它能解決您的問題...

1

另一種方法我會嘗試是通過使用#map

clients.map{ |key, _| key if clients[key] == {"client_id"=>"2180"} }.compact 
#=> ["orange"] 

這將返回給定值的所有出現。下劃線意味着我們不需要鑰匙的價值,因此它不會被分配給變量。如果值不匹配,數組將包含nils - 這就是爲什麼我把#compact放在最後。

0

這裏有一個簡單的方法來找到一個給定值的鍵:

clients = { 
     "yellow"=>{"client_id"=>"2178"}, 
     "orange"=>{"client_id"=>"2180"}, 
     "red"=>{"client_id"=>"2179"}, 
     "blue"=>{"client_id"=>"2181"} 
    } 

    p clients.rassoc("client_id"=>"2180") 

...並找到一個給定鍵的值:

p clients.assoc("orange") 

它會給你的鍵值對。

相關問題