2011-08-21 238 views
11

Rails I18n庫將YAML文件轉換爲可通過虛線路徑調用使用t()函數訪問的數據結構。使用虛線路徑密鑰字符串訪問Ruby哈希

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

有誰知道如何與一個Ruby的Hash做到這一點?或者只能通過YAML對象直接使用?

回答

22

剛上點拆分路徑和迭代此找到合適的哈希?

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 
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 

然後調用它像

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

類似的方法現在在Ruby 2.3中可用,它正是名爲[dig](http://ruby-doc.org/core-2.3.0/Hash.html#method-i-dig) –

1

我建議採取看看這個要點:
https://gist.github.com/potatosalad/760726

它增加了implode

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

或者,你可以在整個結構遞歸迭代建立一個新的哈希explode方法到Hash將嵌套鍵轉換爲單級虛線路徑鍵的對象,反之亦然。

2

有一個寶石太keypath-ruby

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

看代碼(和猜測有關什麼t是),它看起來像你可以這樣做:

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

還有HashDot

HashDot允許在散列上使用點表示法語法。它比使用OpenStruct創建的對象更快,更易於穿越。

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

此代碼不僅允許點符號遍歷散列,而且方括號也可以遍歷具有索引的數組。它也避免了遞歸效率。

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

紅寶石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一步。