[英]How to iterate over deep nested hash without known depth in Ruby
我有多个 YAML(本地化)文件。 我解析它们并在 Ruby 中转换为 hash。
例如,这是其中之一:
hello: Hallo
messages:
alerts:
yay: Da!
no: Nein
deep:
nested:
another:
level:
hi: Hi!
test: Test!
基本上,这看起来像是 Rails App 中使用 YAML 的语言环境文件。
我想要做的是递归地迭代这个 Hash 并获取键和值。 这样我就可以像谷歌翻译一样从 API 端点逐一翻译值。 我想将嵌套哈希保留在相同的模式中,以便 Rails 可以通过键找到。
我知道我可以使用嵌套循环,但不能保证嵌套哈希是已知数量的。 如何递归地迭代这个 hash 以便我可以操纵值(翻译/替换)?
预期结果:(使用 API 调用的翻译服务后)
hello: Hello
messages:
alerts:
yay: Yup!
no: No
deep:
nested:
another:
level:
hi: Hi!
test: Test!
到目前为止我已经尝试过:
hash = YAML.load('de.yml') # parse source Deutsch locale
new_hash = {}
hash.each |key, value| do
new_hash[key] = translate_func(value) # here... translate value then assign very same key including parents.
# Do more loops....
end
# Now write this new_hash to yaml file...
但这只是操纵hello
而已。 为了和其他人一起工作,我必须做一个循环。 但是嵌套了多少键是未知的。
如何遍历区域设置 hash 的所有值并保持架构完整?
如果可能但不是强制性的,如果我们能在最终结果中保持键的顺序,我会非常高兴。 稍后在手动查看时找到丢失的键会很棒。
我对 ruby 很陌生。 我正在使用 Ruby 2.7.2
所有答案都是正确的,我喜欢所有答案。 但是,我希望能够同时控制键和值。 不只是通过价值观转变。 因此,我接受了一个适合我需要的答案。 我能够用选定的答案来完成我的意图。
您可以使用deep_transform_values!
在您的 hash object 上以递归方式更改值。 (或其非破坏性版本deep_transform_values
返回一个新的 hash 而不是更改原始 hash。)
hash.deep_transform_values! { |value| translate_func(value) }
注意: deep_transform_values!
是一种 Rails 方法。 如果您不使用 Rails,请参阅此处的源代码以获得灵感。
因此,您希望递归解析,直到没有更多级别可供解析。
它在软件中非常常见,被称为“递归”。 到处搜索以了解更多信息 - 它会在您的旅程中一次又一次地出现。 欢迎来到 ruby 顺便说一句!
至于您当前的实际问题。 阅读https://mrxpalmeiras.wordpress.com/2017/03/30/how-to-parse-a-nested-yaml-config-file-in-python-and-ruby/
而且,考虑一下 i18n gem。 请参阅此答案https://stackoverflow.com/a/51216931/1777331和 gem https://github.com/ruby-i18n/i18n的文档这可能会解决您在没有您的情况下处理国际化的问题处理 yaml 文件的详细信息。
如果您想要一个简单的非 Rails 解决方案,那么您可以创建一个递归方法:
def recurse(hash)
hash.transform_values do |v|
case v
when String
v.reverse # Just for the sake of the example
when Hash
recurse(v)
else
v
end
end
end
Output:
{"hello"=>"ollaH", "messages"=>{"alerts"=>{"yay"=>"!aD", false=>"nieN"}, "deep"=>{"nested"=>{"another"=>{"level"=>{"hi"=>"!iH"}}}}}, "test"=>"!tseT"}
然而,这可能是重新发明轮子的情况 - 您可以使用 i18n gem 进行翻译,并使用i18n 任务使用来自 Google 翻译 API 的翻译预填充 YAML 文件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.