我有一个嵌套哈希,比如说:
data = {
a: {
b: {
c: {
d: {
e: :f
}
}
}
}
}
另一个哈希:
update = {g: :h}
和路径:
path = [:a, :b, :c, :d]
我想将data
指定的path
的子哈希替换为update
,以便我最终得到:
data == {
a: {
b: {
c: {
d: {
g: :h
}
}
}
}
}
导航到子哈希很容易:
_data = data
path.each{|p| _data = data[p]}
但这不起作用,因为_data = update
更改_data
引用的内容,并且实际上并未更改data[:a][:b][:b][:d]
的值。
虽然我可以编写一个导致子哈希的表达式,但尝试分配它会导致语法错误:
> (path.inject(data){|_data, s| _data[s]}) = update
SyntaxError: unexpected '=', expecting end-of-input
有什么想法吗?
答案 0 :(得分:4)
您可以使用Hash#replace
> path.inject(data){|_data, s| _data[s]}.replace({g: :h})
> data
# => {:a=>{:b=>{:c=>{:d=>{:g=>:h}}}}}
答案 1 :(得分:1)
def substitute(data, path, update)
(data[path.first] = update; return) if path.size == 1
substitute(data[path.first], path.drop(1), update)
end
substitute(data, path, update)
#=> nil
data
#=> {:a=>{:b=>{:c=>{:d=>{:g=>:h}}}}}
要返回data
(以及修改它),请添加data
作为最后一行。
答案 2 :(得分:1)
构建嵌套散列(Ruby 1.8.7)的更新副本的递归解决方案。
def substitute(data, path, update)
if path.empty?
update
else
first, *rest = path
Hash[*data.map { |k, v| first == k ? [k, substitute(v, rest, update)] : [k ,v] }.flatten]
end
end
result = substitute(data, path, update)
puts "In #{data.inspect}" # => In {:a=>{:b=>{:c=>{:d=>{:e=>:f}}}}}
puts "Out #{result.inspect}" # => Out {:a=>{:b=>{:c=>{:d=>{:g=>:h}}}}}