如何使用单个字符串键访问散列的嵌套元素?
我正在和Ruby搞砸,基本上我都有
@trans = { :links => { :quick_notes => "aaaaaaa" } }
我想打个电话
def t #...something end t('links.quick_notes')
访问
trans[:links][:quick_notes]
我基本上试图实现与使用国际化时相同的function
I18n.t('something.other.foo')
我想出了这种方法
def t(key) a='' key.to_s.split('.').each{|key| a+="[:#{key}]" } #now a == "[:links][:quick_notes]" #but I cant figure out how can I call it on @trans variable end t('links.quick_notes')
有任何想法吗 ? 感谢名单
你可以通过inject
到达那里:
def t(key) key.to_s.split('.').inject(@trans) { |h, k| h[k.to_sym] } end
错误检查和“没有这样的条目”检查留作练习。
对于它的价值,这里有一些显示递归使用的 manky代码。
def getKeyChain (obj, parts) if !obj || parts.size == 0 # this is the base case obj else # this is the recursive case key = parts[0] if key.match(/^:/) key = key[1..key.size].to_sym end # each time recursing, pass a new state. # in this case, the value for the "key" and the remaining parts # that need resolving getKeyChain(obj[key], parts[1..parts.size]) end end def getCompoundKey (obj, compound) # helper makes it easier to call while not making the # recursive function more complex. getKeyChain(obj, compound.split(".")) end h0 = {:x => "hello"} h1 = {"a" => {:b => "world"}} puts getCompoundKey(h0, ":x") # => hello puts getCompoundKey(h1, "a.:b") # => world
可以做出许多改进……“使用自己的危险”。
快乐的编码。
如果您正在寻找插入%{variable}
,包括Array支持,我一直在使用它:
def interpolate(string, hash) string.gsub(/%\{([^\}]*)\}/).each { |match| match[/^%{(.*)}$/, 1].split('.').inject(hash) { |h, k| h[(k.to_s == k.to_i.to_s) ? k.to_i : k.to_sym] } } end
由于Ruby 2.3 Hash有一个dig
方法。 “没有这样的条目”检查是内置的:如果缺少任何键,则整个表达式返回nil
。 用法:
@trans = { :links => { :quick_notes => "aaaaaaa" } } def t (str) syms = str.split(".").map(&:to_sym) @trans.dig(*syms) end pt('links.quick_notes') # => "aaaaaaa"
另外一个 – 如果你有json或包含数组和哈希的哈希 – 可能是这样的:
@trans = { :links => [ { :quick_notes => "aaaaaaa" }, { :quick_notes => "bbbbbbb" } ], :page => 1 }
您可以在数组中包含位置测试,您可以执行此类操作。
def t(key) key.split('.').inject(@trans) { |h,v| h.send('[]',v.to_i.to_s.eql?(v) ? v.to_i : v) } end
这将允许您传递这样的密钥
t('links.1.quick_notes')
得到答案’bbbbbb’