从数组值中获取对应的键

Get corresponding key from an array value

我有一个哈希值是数组:

@@words = {
    "direction" => ["north", "south", "west"],
    "verb" => ["go", "jump"]
  }

如果我做 @@words.key("north"),它将 return error 而不是 direction。我如何让它正常工作?

您可以使用Enumerable#select

@@words
=> {"direction"=>["north", "south", "west"], "verb"=>["go", "jump"]}
@@words.select { |_, v| v.include?("north") }
=> {"direction"=>["north", "south", "west"]}
@@words.select { |_, v| v.include?("north") }.keys
=> ["direction"]

map的替代方案:

@@words.map { |k, v| k if v.include?("north") }.compact
=> ["direction"]
@@words.find { |_, value| value.include? 'north' }.first
@@words = {
    "direction" => ["north", "south", "west"],
    "verb" => ["go", "jump"]
  }

@@words.find { |_,(v,*_)| v == "north" }
  #=> ["direction", ["north", "south", "west"]] 

or 

@@words.find { |_,(v,*_)| v == "north" }.first
  #=> "direction"

取决于您的要求。我假设 "north" 是值数组的第一个元素。

变体:

@@words.keys.find { |k| @@words[k].first == "north" }

您询问了以下中的块变量:

@@words.find { |_,(v,*_)| v == "north" }

我结合使用了并行赋值和分解(或消除歧义,这个词我觉得有点普通)。我们有:

enum = @@words.find
  #=> #<Enumerator: {"direction"=>["north", "south", "west"],
  #                  "verb"=>["go", "jump"]}:find>

enum的两个元素将被传递到块中,可以通过将其转换为数组来查看:

enum.to_a
  #=> [["direction", ["north", "south", "west"]],
  #    ["verb", ["go", "jump"]]]

enum 的第一个值传递给块时,块变量设置如下:

k,(v,*rest) = enum.next #=> ["direction", ["north", "south", "west"]] 
k                       #=> "direction" 
v                       #=> "north" 
rest                    #=> ["south", "west"] 

我不会在块计算中使用krest,所以我选择将两者替换为局部变量_,主要是为了引起注意那些变量没有被使用的事实,也是为了减少块计算出错的机会。

顺便说一下,在 class 之外使用 class 变量是没有意义的,而且根本没有理由使用它。通常(总是?)使用 class 实例变量比 class 变量更可取。如果您不熟悉前者,那将是另一天的教训。

一些猴子补丁来拯救:-)

words = {
    "direction" => ["north", "south", "west"],
    "verb" => ["go", "jump"],
    "test" => "me"
}

class Hash 
  def key_ (value)
    key(value) || key(self.select { |k, v| v.include?(value)}.values.first)
  end
end

puts words.key_("south")  # direction
puts words.key_("go")     # verb
puts words.key_("me")     # test

self.select { |k, v| v.include?(value)}.values.first 表示其中存在 value 的数组,因此现在我们可以使用内置的 Hash#key method 来查找密钥。

该代码还通过首先调用 key(value) 来处理 Hash 的值不全是数组的情况,如果是 nil,则再次尝试认为可能是 value 作为数组成员出现在 Hash#values 之一中。

这个解决方案可以扩展到包括嵌套哈希和其他数据类型。