【问题标题】:Get corresponding key from an array value从数组值中获取对应的键
【发布时间】:2015-11-19 14:45:23
【问题描述】:

我有一个哈希值是数组:

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

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

【问题讨论】:

  • 必须“north”是数组的第一个元素还是数组的任何元素?
  • 詹姆斯,请回答。 @Wand,我认为它可以被解释为任何一种方式。假设words = { "Jones" => ["Bob", "chief underling"], "Cher" => ["", "singer and actor"]。而你想要那个没有名字的人。
  • 无法复制。
  • 我问了一个很简单的问题。当你没有回答时,我又问了一遍。再次,你没有回答。你没学过礼仪吗?

标签: arrays ruby hash key


【解决方案1】:
@@words.find { |_, value| value.include? 'north' }.first

【讨论】:

  • 你有tick 图标来催眠OP 接受你的答案吗?或者欺骗人们认为你的答案是公认的答案?它确实适用于第二种情况:-)
  • @WandMaker,你低估了人类。这只是最正确和最准确的解决方案 atm。 :)
  • @JamesMitchell,这是一个成语。我本可以在那里使用key,但惯例是,如果您对某事不感兴趣,您应该将其命名为_(就像这里的情况一样,我没有直接访问key 变量)。跨度>
  • @Wand,技术术语是“subliminal stimuli”。
  • @Wand,类似于this?
【解决方案2】:
@@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"

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

一个变种:

@@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,所以我选择将两者都替换为局部变量_,主要是为了提醒大家注意这些变量不是被使用,同时也减少了块计算出错的机会。

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

【讨论】:

  • 好的,我试试看。您愿意解释一下 ,(v,*) 语法吗?我想尝试确切地了解这个答案的作用。
  • 我相信 OP 想要数组中包含的值的键,例如'south' 仍然会像 'west' 一样返回“direction”,但 'jump' 会返回“verb”。话虽这么说,但对语法利用很赞。
  • 如果我使用"south" 而不是"north",那么,我在第三个变体中得到undefined method 'first' for nil:NilClass (NoMethodError)
  • @engineersmnky 和魔杖,不一定。关于这个问题,请参阅我的 cmets。
【解决方案3】:

您可以使用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"]

【讨论】:

    【解决方案4】:

    一些猴子修补来救援:-)

    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) 来处理哈希值不是所有数组的情况,如果是nil,那么它会再次尝试认为value 可能存在于其中一个Hash#values 作为数组成员。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多