2010-09-25 51 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") 

它会给你的键值对。

相关问题