Ruby on rails 使用虚线路径键字符串访问Ruby哈希

Ruby on rails 使用虚线路径键字符串访问Ruby哈希,ruby-on-rails,ruby,hash,key,yaml,Ruby On Rails,Ruby,Hash,Key,Yaml,Rails I18n库将YAML文件转换为数据结构,可以使用t()函数通过点路径调用访问该数据结构 t('one.two.three.four') 有人知道如何使用Ruby哈希实现这一点吗?还是只能通过YAML对象直接实现?是的,我不认为这是内置的,在其他任何地方。但我在我的一个项目中使用了类似的东西: class Hash def dig(dotted_path) parts = dotted_path.split '.', 2 match = self[parts[0]

Rails I18n库将YAML文件转换为数据结构,可以使用t()函数通过点路径调用访问该数据结构

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

有人知道如何使用Ruby哈希实现这一点吗?还是只能通过YAML对象直接实现?

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

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' => 'a-d-e'}}, 'f' => 'f'}
my_hash.dig('a.d.e') # outputs 'a-d-e' (by calling my_hash['a']['d']['e'])

只需在路径中的一个点上拆分,然后迭代以找到正确的散列

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

我建议看一下要点:

它将
内爆
分解
方法添加到
哈希
对象,该对象将嵌套键转换为单级点路径键,反之亦然。

还有一个Gem

查看代码(并猜测一下
t
是什么),您似乎可以这样做:

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

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

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

这段代码不仅允许点表示法遍历散列,还允许方括号遍历具有索引的数组。为了提高效率,它还避免了递归

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("b.c[-1][1]") # => 42
Ruby 2.3引入了查找嵌套数组/哈希的方法,当找不到数据时,它返回
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)

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

Ruby 2.3中现在提供了一个类似的方法,它被精确地调用
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)