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

mat*_*sko 14 ruby hash yaml ruby-on-rails key

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

t('one.two.three.four')
Run Code Online (Sandbox Code Playgroud)

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

Mon*_*uïe 25

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

path.split(".").inject(hash) { |hash, key| hash[key] }
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)


Dav*_*sta 12

红宝石2.3介绍了dig方法,看起来成嵌套阵列/散列,则返回nil当没有数据被发现.

例如:

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

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


chb*_*own 10

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

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
Run Code Online (Sandbox Code Playgroud)

然后称之为

my_hash = {'a' => {'b' => 'a-b', 'c' => 'a-c', 'd' => {'e' => 'a-d-e'}}, 'f' => 'f'}
my_hash.dig('a.d.e') # outputs 'a-d-e' (by calling my_hash['a']['d']['e'])
Run Code Online (Sandbox Code Playgroud)

  • 类似的方法现在可以在Ruby 2.3中使用了,它被称为[dig](http://ruby-doc.org/core-2.3.0/Hash.html#method-i-dig) (2认同)