【问题标题】: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"}
}

【问题讨论】:

    标签: ruby


    【解决方案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.7clients.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") 
            

            它会给你键值对。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2014-05-25
              • 2017-08-02
              • 2011-08-27
              • 1970-01-01
              • 2015-04-25
              • 1970-01-01
              • 2013-04-07
              • 1970-01-01
              相关资源
              最近更新 更多