如何找到包含匹配值的哈希键
Posted
技术标签:
【中文标题】如何找到包含匹配值的哈希键【英文标题】:How to find a hash key containing a matching value 【发布时间】:2011-04-17 04:20:07 【问题描述】:鉴于我有以下 clients 哈希,是否有一种快速的 ruby 方法(无需编写多行脚本)来获取我想要匹配 client_id 的密钥?例如。如何获取client_id == "2180"
的密钥?
clients =
"yellow"=>"client_id"=>"2178",
"orange"=>"client_id"=>"2180",
"red"=>"client_id"=>"2179",
"blue"=>"client_id"=>"2181"
【问题讨论】:
【参考方案1】:Ruby 1.9 及更高版本:
hash.key(value) => key
Ruby 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")
【讨论】:
如果哈希有多个键,这会有点混乱,因为您需要将整个哈希提供给index
。
Hash#index
在 Ruby 1.9 中重命名为 Hash#key
注意这里只返回第一个匹配,如果有多个相同值的哈希配对,它会返回第一个匹配值的键。【参考方案2】:
你可以使用Enumerable#select:
clients.select|key, hash| hash["client_id"] == "2180"
#=> [["orange", "client_id"=>"2180"]]
请注意,结果将是所有匹配值的数组,其中每个都是键和值的数组。
【讨论】:
@Coderamafind
和select
的区别在于find
返回第一个匹配项,select
(别名为findAll
)返回所有匹配项。
我明白了,所以对于有多个匹配项的情况,这将是更安全的选择。
这比创建一个全新的哈希(通过调用invert
)只是为了找到一个项目要好。
请注意,从Ruby 1.9.3 开始,这将返回一个包含匹配项的新哈希。它不会返回数组,因为它是used to in Ruby <= 1.8.7。 clients.select|key, hash| hash["client_id"] == "2180" # => "orange"=>"client_id"=>"2180"
要获取密钥,只需输入clients.select|key, hash| hash["client_id"] == "2180" .keys
【参考方案3】:
您可以反转哈希。 clients.invert["client_id"=>"2180"]
返回"orange"
【讨论】:
这似乎也是一个聪明的方法(因为它很短)! 这是我需要的创建反向散列的表单数组(用于选择框)【参考方案4】:你可以使用 hashname.key(valuename)
或者,可能需要反转。 new_hash = hashname.invert
会给你一个new_hash
,让你做更传统的事情。
【讨论】:
这是 Ruby 最新版本 (1.9+) 中的正确方法。#invert
在这种情况下是一个非常糟糕的主意,因为您实际上只是为了找到一个键而为一次性哈希对象分配内存。根据哈希大小,它会对性能产生严重影响【参考方案5】:
试试这个:
clients.find|key,value| value["client_id"] == "2178".first
【讨论】:
如果 find 返回 nil 会抛出异常,因为你不能在 nil 上调用 .first。 如果使用 Rails,您可以使用.try(:first)
而不是 .first
以避免异常(如果您期望值可能会丢失)。
在Ruby 2.3.0 +
你可以在块的末尾使用safe navigator&.first
来防止Nil Exception【参考方案6】:
根据 ruby doc http://www.ruby-doc.org/core-1.9.3/Hash.html#method-i-keykey(value) 是根据 value 找到 key 的方法。
ROLE = "customer" => 1, "designer" => 2, "admin" => 100
ROLE.key(2)
它将返回“设计器”。
【讨论】:
【参考方案7】:来自文档:
(对象?)检测(ifnone = nil)|obj| ... (对象?)查找(ifnone = nil)|obj| ... (对象)检测(ifnone = nil) (对象)查找(ifnone = nil)将枚举中的每个条目传递给阻塞。返回第一个不为假的块。如果没有对象匹配,则调用 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
【讨论】:
【参考方案8】:找到特定值的键的最佳方法是使用可用于哈希的键方法....
gender = "MALE" => 1, "FEMALE" => 2
gender.key(1) #=> MALE
希望能解决你的问题……
【讨论】:
【参考方案9】:我会尝试的另一种方法是使用#map
clients.map |key, _| key if clients[key] == "client_id"=>"2180" .compact
#=> ["orange"]
这将返回给定值的所有出现。下划线意味着我们不需要携带键的值,这样它就不会被分配给变量。如果值不匹配,数组将包含 nils - 这就是我将 #compact
放在末尾的原因。
【讨论】:
【参考方案10】:这是一种查找给定值的键的简单方法:
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")
它会给你键值对。
【讨论】:
以上是关于如何找到包含匹配值的哈希键的主要内容,如果未能解决你的问题,请参考以下文章