Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
260 views
in Technique[技术] by (71.8m points)

How to iterate over deep nested hash without known depth in Ruby

I have multiple YAML (localization) files. I parse them and convert to hash in Ruby.

For example this is one of them:

hello: Hallo
messages:
  alerts:
    yay: Da!
    no: Nein
  deep:
    nested:
      another:
        level:
          hi: Hi!
test: Test!

Basically, this is look like a locale file in Rails App using YAML.

What I want to do is iterate this Hash recursively and get key and value. So that i can translate values one-by-one from API Endpoint like Google Translate. I want to keep nested hashes in same schema so that Rails can find by keys.

I know i can use nested loops but there is no guarantee that nested hashes is a known number of. How can I iterate this hash recursively so i can manipulate values (translate/replace)?

Expected Result: (after used translation service from API call)

hello: Hello
messages:
  alerts:
    yay: Yup!
    no: No
  deep:
    nested:
      another:
        level:
          hi: Hi!
test: Test!

What I've tried so far:

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...

But this only manipulate hello only. To get work with others I have to make a loop. But how many keys are nested is unknown.

How can I iterate over all values of locale hash and keep the schema intact?

And if possible but not mandatory, I would be very happy if we can keep the order of keys on final result. That would be awesome to find missing keys later when manually reviewed.

I am very new to ruby. I am using Ruby 2.7.2

Conclusion / Resolve

All answers are correct and I love all of them. However, I would like to be able to control both keys and values. Not just transform by values. Therefore, I accepted an answer that fits to my needs. I was able to do my intention with selected answer.

question from:https://stackoverflow.com/questions/65864615/how-to-iterate-over-deep-nested-hash-without-known-depth-in-ruby

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

So, you want to parse recursively until there are no more levels to parse into.

It’s super common in software and referred to as “recursion”. Have a search around to learn more about it - it’ll come up again and again in your journey. Welcome to ruby btw!

As for your actual current problem. Have a read of https://mrxpalmeiras.wordpress.com/2017/03/30/how-to-parse-a-nested-yaml-config-file-in-python-and-ruby/

But also, consider the i18n gem. See this answer https://stackoverflow.com/a/51216931/1777331 and the docs for the gem https://github.com/ruby-i18n/i18n This might fix your problem of handling internationalisation without you having to get into the details of handling yaml files.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...