[英]Recursively modify values in a nested hash
鉴于以下 hash 结构,我想遍历该结构并使用“链接”键对所有值进行修改:
{"page_id":"12345", "link_data":{"message":"test message", "link":"https://www.example.com", "caption":"https://www.example.com", "child_attachments":[{"link":"http://www.example.com", "name":"test", "description":"test", "picture":"https://fbcdn-creative-a.akamaihd.net/hads-ak-xap1/t45.1600-4/10736595_6021553533580_1924611765_n.png"}, {"link":"http://www.example.com", "name":"test", "description":"test", "picture":"https://fbcdn-creative-a.akamaihd.net/hads-ak-xaf1/t45.1600-4/10736681_6021625991180_305087686_n.png"}, {"link":"http://www.example.com", "name":"test", "description":"test 2", "picture":"https://fbcdn-creative-a.akamaihd.net/hads-ak-xfp1/t45.1600-4/10736569_6020761399780_1700219102_n.png"}]}}
我一直在使用的方法对我来说有点错误,因为我检查了所有值以查看它们是否具有与应该是 URL 匹配的模式,然后在此时对其进行修改:
def find_all_values_for(key)
result = []
result << self[key]
self.values.each do |hash_value|
if hash_value.to_s =~ URI::regexp # if the value looks like a URL then change it
# update the url
end
end
end
因此,转换的确切最终结果应该与 URL 修改后的 hash 相同。 我真正想做的是将跟踪参数添加到 hash 中的每个 URL 中。
我玩弄了将 hash 转换为字符串并对其执行一些字符串替换的想法,但这似乎不是做这种事情的最干净的方法。
干杯
也许这样的事情?
def update_links(hash)
hash.each do |k, v|
if k == "link" && v.is_a?(String)
# update link here
v.replace "a modification"
elsif v.is_a?(Hash)
update_links v
elsif v.is_a?(Array)
v.flatten.each { |x| update_links(x) if x.is_a?(Hash) }
end
end
hash
end
接受的答案在 ruby 2.5+ 中根本不起作用。 您不能就地修改 hash。 你会得到一个冻结的字符串错误:
`replace': can't modify frozen String: "..." (FrozenError)
相反,您可以使用修改后的键/值对创建一个新的 hash:
def update_links(hash)
hash.reduce({}) do |acc, (key,value)|
if value.is_a?(Hash)
acc[key.underscore] = update_links(value)
else
acc[key.underscore] = value
end
acc
end
end
在这个简单的演示中,它强调了键,而没有就地修改它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.