使用虚线路径密钥字符串访问Ruby哈希

Rails I18n库将YAML文件转换为可通过使用t()函数的虚线路径调用访问的数据结构。

t('one.two.three.four') 

有没有人知道如何用Ruby Hash做到这一点? 或者只能直接通过YAML对象?

只是在路径中的一个点上拆分并迭代这个以找到正确的哈希?

 path.split(".").inject(hash) { |hash, key| hash[key] } 

或者,您可以通过在整个结构上递归迭代来构建新哈希:

 def convert_hash(hash, path = "") hash.each_with_object({}) do |(k, v), ret| key = path + k if v.is_a? Hash ret.merge! convert_hash(v, key + ".") else ret[key] = v end end end 

是的,我不认为这是内置的,在其他任何地方。 但我在我的一个项目中使用了类似的东西:

 class Hash def dig(dotted_path) parts = dotted_path.split '.', 2 match = self[parts[0]] if !parts[1] or match.nil? return match else return match.dig(parts[1]) end end end 

然后称之为

 my_hash = {'a' => {'b' => 'a-b', 'c' => 'a-c', 'd' => {'e' => 'ad-e'}}, 'f' => 'f'} my_hash.dig('ade') # outputs 'ade' (by calling my_hash['a']['d']['e']) 

Ruby 2.3引入了查看嵌套数组/哈希的dig方法 ,当没有找到数据时返回nil

例如:

 test_data = {a: {b: {c: {d: 1}, e: 2}}} path = 'abcd'.split('.').map(&:to_sym) # path => [:a, :b, :c, :d] test_data.dig(*path) 

当然,如果您的嵌套使用字符串键,则不需要to_sym步骤。

还有一个Gem太keypath-ruby

 gem 'key_path', :git => 'https://github.com/nickcharlton/keypath-ruby.git' 

查看代码(并猜测一下t是什么),看起来你可以这样做:

 t.value_at_keypath('one.two.three.four') 

此代码不仅允许点符号遍历哈希,还允许使用方括号来遍历带索引的数组。 它还避免了递归效率。

 class Hash def key_path(dotted_path) result = self dotted_path.split('.').each do |dot_part| dot_part.split('[').each do |part| if part.include?(']') index = part.to_i result = result[index] rescue nil else result = result[part] rescue nil end end end result end end 

例:

 a = {"b" => {"c" => [0, [1, 42]]}} a.key_path("bc[-1][1]") # => 42 

我建议你看看这个要点:
https://gist.github.com/potatosalad/760726

它将内嵌和explode方法添加到Hash对象,将嵌套键转换为单级虚线路径键,反之亦然。

还有HashDot 。

HashDot允许在哈希上使用点表示法语法。 它比使用OpenStruct创建的对象更快,更可遍历。

 a = {b: {c: {d: 1}}} abcd => 1