如何找到包含匹配值的哈希键

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"]]

请注意,结果将是所有匹配值的数组,其中每个都是键和值的数组。

【讨论】:

@Coderamafindselect的区别在于find返回第一个匹配项,select(别名为findAll)返回所有匹配项。 我明白了,所以对于有多个匹配项的情况,这将是更安全的选择。 这比创建一个全新的哈希(通过调用invert)只是为了找到一个项目要好。 请注意,从Ruby 1.9.3 开始,这将返回一个包含匹配项的新哈希。它不会返回数组,因为它是used to in Ruby <= 1.8.7。 clients.select|key, hash| hash["client_id"] == "2180" # =&gt; "orange"=&gt;"client_id"=&gt;"2180" 要获取密钥,只需输入clients.select|key, hash| hash["client_id"] == "2180" .keys【参考方案3】:

您可以反转哈希。 clients.invert["client_id"=&gt;"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&amp;.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") 

它会给你键值对。

【讨论】:

以上是关于如何找到包含匹配值的哈希键的主要内容,如果未能解决你的问题,请参考以下文章

在 Ruby 中找到第一个可能匹配的哈希键的优雅方式

迭代时无意中将键添加到哈希

Javascript:从包含对象的多维数组中返回不匹配的值

从 Ruby 哈希中转移一个特定的匹配键值对

如何从海量数据中找到相似数据--那些用于查找相似数据的哈希算法

Scala:如何将模式匹配功能应用于包含以下值的 csv 文件