使用键数组遍历嵌套的Ruby哈希表

4

给定一个具有n个嵌套值的哈希表、一个字段名称和一个路径

contact = {
  "Email" => "bob@bob.com",
  "Account" => {
    "Exchange" => true,
    "Gmail" => false,
    "Team" => {
      "Closing_Sales" => "Bob Troy",
      "Record" => 1234
    }
  }
}

field = "Record"
path = ["Account", "Team"] #Must support arbitrary path length

如何定义一个方法,以检索路径末端的字段值。
def get_value(hash, field, path)
  ?
end

get_value(contact, "Record", ["Account", "Team"])
=> 1234

1
你的问题写得很好。下次在选择答案之前考虑等待更长时间。快速选择可能会阻碍其他回答并打断那些仍在回答的人。 (然而,在我开始写我的答案之前,你已经选择了一个答案。) - Cary Swoveland
你好 @CarySwoveland - 感谢您的建议,下次我一定会这样做。我刚开始真正使用StackExchange,所以我有点新手。您的答案非常好。 - Nicholas Erdenberger
3个回答

4
你可以使用Array#inject来表示hash['Account']['Team'],然后返回return_value_of_inject['Record']
def get_value(hash, field, path)
  path.inject(hash) { |hash, x| hash[x] }[field]
end

get_value(contact, field, path) # => 1234

顺便问一下,get_value(contact, ['Account', 'Team', 'Record']) 怎么样?

def get_value2(hash, path)
  path.inject(hash) { |hash, x| hash[x] }
end

get_value2(contact, ['Account', 'Team', 'Record']) # => 1234

或者get_value(contact,'Account.Team.Record')
def get_value3(hash, path)
  path.split('.').inject(hash) { |hash, x| hash[x] }
end

get_value3(contact, 'Account.Team.Record')   # => 1234

4
让我们将“字段”视为“路径”的最后一个元素。那么这就很简单了。
def grab_it(h, path)
  h.dig(*path)
end

grab_it contact, ["Account", "Team", "Record"]
  #=> 1234 
grab_it contact, ["Account", "Team", "Rabbit"]
  #=> nil
grab_it(contact, ["Account", "Team"]
  # => {"Closing_Sales"=>"Bob Troy", "Record"=>1234} 
grab_it contact, ["Account"]
  #=> {"Exchange"=>true, "Gmail"=>false, "Team"=>{"Closing_Sales"=>"Bob Troy",
  #    "Record"=>1234}} 

Hash#dig was added in v2.3.


1
def get_value(contact, field, path)
  path.inject(contact) {|p, j| p.fetch(j, {}) }.fetch(field, nil)
end

你可以通过写 (path + [field]).inject(contact) {|p, j| p.fetch(j, {}) } 来简化代码。 - Cary Swoveland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接