我有像这样的哈希,代表一个数据树
hash = {
'key1' => {
'sub1' => 1,
'sub2' => 2
},
'key2' => 3
}
我想用一组表示路径的键来探索树。 一些例子:
用简单的路径:
keys = ['key2']
我想获得3
使用此路径:
keys = ['key1', 'sub1']
我想获得1
带有荣耀路径:
keys = ['key1', 'sub1', 'blabla']
keys = ['key1', 'blabla']
获取nil
答案 0 :(得分:7)
keys.inject(hash) {|acc, value| acc[value]}
答案 1 :(得分:4)
不进行任何错误检查,但
h = {'k1' => {'s1' => 1, 's2' => 2}, 'k2' => 3}
ks = ['k1', 's1']
ks.inject(h){|hh, k| hh[k]} # => 1
['k1', 's2'].inject(h){|hh, k| hh[k]} # => 2
['k2'].inject(h){|hh, k| hh[k]} # => 3
答案 2 :(得分:2)
最好记住对象,所以让我们为Hash类添加一个功能
# in intialize or whatever
class Hash
def find_path path #recursive
key = path.first
if _path.size == 1 # end of path => return value
[key]
elsif [key].kind_of?(Hash) # continue
[key].find_path path[1..-1]
else # have to continue but not a has => out
nil
end
end
def find_path path # not recursive
_path = path.clone #copy to shift
_tree = self #start with self
while(_path.size > 1 && _tree) do #while not the end and _tree
_v = _tree[_path.shift]
_tree = _v.kind_of?(Hash) ? _v : nil
end
_tree ? _tree[_path.first] : nil
end
end
这样:
hash = {:v1 => {:v1.1 => "yes", :v1.2 => "false"}}
hash.find_path [:v1, :v1.1]
# => "yes"
hash.find_path [:v1]
# => {:v1.1 => "yes", :v1.2 => "false"}
hash.find_path [:v2]
# => nil
hash.find_path [:v1, :v1.3]
# => nil
答案 3 :(得分:1)
这是我的解决方案(它类似于proxygear,但它没有修补Hash,并且在没有args的情况下调用它时表现正常)。我认为它比两个基于注入的解决方案更好,因为如果你试图访问DNE的路径,它们会爆炸。
class TraversibleHash
attr_accessor :hash
def initialize(hash)
self.hash = hash
end
def access(*keys)
recursive_access keys, hash
end
private
def recursive_access(keys, hash)
return nil if keys.empty?
element = hash.fetch(keys.shift) { return nil }
return element if keys.empty?
return nil unless element.kind_of? Hash # <-- should maybe raise an error?
recursive_access keys, element
end
end
以下是测试套件:
describe TraversibleHash do
let(:traversible) { TraversibleHash.new 'key1' => { 'sub1' => 1, 'sub2' => 2 }, 'key2' => 3, nil => 1 }
it 'returns nil when invoked without args' do
traversible.access.should be_nil
end
it 'returns nil when accessing nonexistent keys' do
traversible.access('key3').should be_nil
traversible.access('key2', 'key3').should be_nil
traversible.access('key1', 'sub3').should be_nil
traversible.access('key1', 'sub2', 'subsub1').should be_nil
traversible.access('abc', 'def', 'ghi').should be_nil
end
it 'finds toplevel keys' do
traversible.access('key2').should == 3
traversible.access('key1').should == {'sub1' => 1, 'sub2' => 2}
end
it 'traverses nested hashes to find nested keys' do
traversible.access('key1', 'sub1').should == 1
traversible.access('key1', 'sub2').should == 2
TraversibleHash.new(1=>{2=>{3=>4}}).access(1, 2, 3).should == 4
end
end
答案 4 :(得分:0)