使用点分路径键字符串访问 Ruby 哈希

Posted

技术标签:

【中文标题】使用点分路径键字符串访问 Ruby 哈希【英文标题】:Access Ruby Hash Using Dotted Path Key String 【发布时间】:2011-10-31 15:41:50 【问题描述】:

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

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

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

【问题讨论】:

【参考方案1】:

只需在路径中的一个点上拆分并对其进行迭代以找到正确的哈希?

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

【讨论】:

【参考方案2】:

Ruby 2.3 引入了dig method,它查看嵌套数组/哈希,当没有找到数据时返回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 步骤。

【讨论】:

【参考方案3】:

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

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'])

【讨论】:

现在 Ruby 2.3 中提供了一个类似的方法,它的名字正好是 dig【参考方案4】:

也有宝石keypath-ruby

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

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

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

【讨论】:

【参考方案5】:

此代码不仅允许点表示法遍历哈希,还允许方括号遍历具有索引的数组。它还避免了递归以提高效率。

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

【讨论】:

【参考方案6】:

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

它将implodeexplode 方法添加到Hash 对象,将嵌套键转换为单级点路径键,反之亦然。

【讨论】:

【参考方案7】:

还有HashDot。

HashDot 允许在哈希上使用点符号语法。它比使用 OpenStruct 创建的对象更快、更易遍历。

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

【讨论】:

以上是关于使用点分路径键字符串访问 Ruby 哈希的主要内容,如果未能解决你的问题,请参考以下文章

如果值递归包含字符串,Ruby 返回***哈希键

为啥关键字参数必须作为带有符号键的哈希传递,而不是 Ruby 中的字符串键?

为啥 Ruby 象征着我的哈希键?

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

默认情况下如何使用字符串键创建哈希

为啥哈希中的这个字符串键被转换为符号?