Iterate over a deeply nested level of hashes in Ruby

Iterate over a deeply nested level of hashes in Ruby

ruby iterate over array of hashes
ruby select value from array of hashes
ruby iterate over hash
ruby find key in nested hash
ruby array of hashes get value
ruby select nested hash
ruby hash
ruby hash delete nested key

So I have a hash, and for each level of the hash, I want to store its key and value. The problem is, a value can be another hash array. Furthermore, that hash can contain key value pairs where the value is again another hash array, etc, etc. Also, I won't know how deeply nested each hash will be. To give an example:

{
  :key1 => 'value1',
  :key2 => 'value2',
  :key3 => {
     :key4 => 'value4',
     :key5 => 'value5'
   },
    :key6 => {
      :key7 => 'value7',
      :key8 => {
        :key9 => 'value9'
      }
    }
  }

..And so on. What I want to do is save each key, value pair and the id of its parent. I figure this will probably be done recursively, I'm just unsure how because I'm unfamiliar with recursive functions. I know how to iterate through the data normally:

  myHash.each {|key, value|
    ...Do something with the key and value ...
  }

And so I'm guessing the recursive call will be something like this:

def save_pair (myHash)
  myHash.each {|key, value|
    if(value.class != Hash) ? Pair.create(key, value) : save_pair(value)
  }
end

This is untested, and I'm still unsure how to incorporate saving the parent ids regardless.


If I understand the goal, then you should be able to pass in the parent to your save method. For the top level, it will be nil. The following shows the idea where puts is used as a place holder for the "save".

def save_pair(parent, myHash)
  myHash.each {|key, value|
    value.is_a?(Hash) ? save_pair(key, value) :
            puts("parent=#{parent.nil? ? 'none':parent}, (#{key}, #{value})")
  }
end

Here is an example call to it:

hash = Hash.new
hash["key1"] = "value1"
hash["key2"] = "value2"
hash["key3"] = Hash.new
hash["key3"]["key4"] = "value4"
hash["key3"]["key5"] = "value5"
hash["key6"] = Hash.new
hash["key6"]["key7"] = "value7"
hash["key6"]["key8"] = Hash.new
hash["key6"]["key8"]["key9"] = "value9"

save_pair(nil, hash)

Nested Hash Iteration Code Along, You can directly iterate over the hash that is the value of the "Freddy Mercury" key by calling an enumerator method in contacts["Freddy Mercury"] . Looping Through a Nested Hash. The best way to understand a nested loop is this: the first iteration loops through the outer hash and its key/value pair, and the second iteration loops through the inner hash and its key/value pair.


I know this is a late reply, but I just implemented a non-recursive solution to your problem and thought it is worth sharing.

class Hash
  def deep_traverse(&block)
    stack = self.map{ |k,v| [ [k], v ] }
    while not stack.empty?
      key, value = stack.pop
      yield(key, value)
      if value.is_a? Hash
        value.each{ |k,v| stack.push [ key.dup << k, v ] }
      end
    end
  end
end

Then, coming back to your original problem, you can do:

h = {
  :key1 => 'value1',
  :key2 => 'value2',
  :key3 => {
     :key4 => 'value4',
     :key5 => 'value5'
  },
  :key6 => {
    :key7 => 'value7',
    :key8 => {
      :key9 => 'value9'
    }
  }
}
h.deep_traverse{ |path,value| p [ path, value ] }
# => [[:key6], {:key7=>"value7", :key8=>{:key9=>"value9"}}]
#    [[:key6, :key8], {:key9=>"value9"}]
#    [[:key6, :key8, :key9], "value9"]
#    [[:key6, :key7], "value7"]
#    [[:key3], {:key4=>"value4", :key5=>"value5"}]
#    [[:key3, :key5], "value5"]
#    [[:key3, :key4], "value4"]
#    [[:key2], "value2"]
#    [[:key1], "value1"]

There is also a gist version.

Nested Arrays, Hashes & Loops in Ruby, Nested arrays are useful when storing things in multiple categories. There can be multiple levels of nesting. If we were to iterate through the outer array in more_nested_array, only the first layer inside the array would be� Iterating Over Hashes Because hashes can have multiple elements in them, there will be times when you'll want to iterate over a hash to do something with each element. Iterating over hashes is similar to iterating over arrays with some small differences. We'll use the each method again and this time we'll create a new file to test this out.


class Hash
  def each_with_parent(parent=nil, &blk)
    each do |k, v|
      Hash === v ? v.each_with_parent(k, &blk) : blk.call([parent, k, v])
    end
  end
end

h = { :a => 1, :b => { :c => 3, :d => 4, :e => { :f => 5 } } }

h.each_with_parent { |i| p i }
# [nil, :a, 1]
# [:b, :c, 3]
# [:b, :d, 4]
# [:e, :f, 5]

Iterate over hash of nested hashes - Ruby, If the values are hashes, I'd like to iterate over them and keep this up until the values aren't hashes. And I won't know how many level there will� Nested hash iteration: How to iterate a merge over an ( (array of hashes) within a hash ) The nested hash below before alteration: ruby arrays hash nested


Here is recursive (read improved) version of Hash::each(Hash::each_pair) with block and enumerator support:

module HashRecursive
    refine Hash do
        def each(recursive=false, &block)
            if recursive
                Enumerator.new do |yielder|
                    self.map do |key, value|
                        value.each(recursive=true).map{ |key_next, value_next| yielder << [[key, key_next].flatten, value_next] } if value.is_a?(Hash)
                        yielder << [[key], value]
                    end
                end.entries.each(&block)
            else
                super(&block)
            end
        end
        alias_method(:each_pair, :each)
    end
end

using HashRecursive

Here are usage examples of Hash::each with and without recursive flag:

hash = {
    :a => {
        :b => {
            :c => 1,
            :d => [2, 3, 4]
        },
        :e => 5
    },
    :f => 6
}

p hash.each, hash.each {}, hash.each.size
# #<Enumerator: {:a=>{:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}, :f=>6}:each>
# {:a=>{:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}, :f=>6}
# 2

p hash.each(true), hash.each(true) {}, hash.each(true).size
# #<Enumerator: [[[:a, :b, :c], 1], [[:a, :b, :d], [2, 3, 4]], [[:a, :b], {:c=>1, :d=>[2, 3, 4]}], [[:a, :e], 5], [[:a], {:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}], [[:f], 6]]:each>
# [[[:a, :b, :c], 1], [[:a, :b, :d], [2, 3, 4]], [[:a, :b], {:c=>1, :d=>[2, 3, 4]}], [[:a, :e], 5], [[:a], {:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}], [[:f], 6]]
# 6

hash.each do |key, value|
    puts "#{key} => #{value}"
end
# a => {:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}
# f => 6

hash.each(true) do |key, value|
    puts "#{key} => #{value}"
end
# [:a, :b, :c] => 1
# [:a, :b, :d] => [2, 3, 4]
# [:a, :b] => {:c=>1, :d=>[2, 3, 4]}
# [:a, :e] => 5
# [:a] => {:b=>{:c=>1, :d=>[2, 3, 4]}, :e=>5}
# [:f] => 6

hash.each_pair(recursive=true) do |key, value|
    puts "#{key} => #{value}" unless value.is_a?(Hash)
end
# [:a, :b, :c] => 1
# [:a, :b, :d] => [2, 3, 4]
# [:a, :e] => 5
# [:f] => 6

Here is example from the question itself:

hash = {
    :key1   =>  'value1',
    :key2   =>  'value2',
    :key3   =>  {
        :key4   =>  'value4',
        :key5   =>  'value5'
    },
    :key6   =>  {
        :key7   =>  'value7',
        :key8   =>  {
            :key9   =>  'value9'
        }
    }
}

hash.each_pair(recursive=true) do |key, value|
    puts "#{key} => #{value}" unless value.is_a?(Hash)
end
# [:key1] => value1
# [:key2] => value2
# [:key3, :key4] => value4
# [:key3, :key5] => value5
# [:key6, :key7] => value7
# [:key6, :key8, :key9] => value9

Also take a look at my recursive version of Hash::merge(Hash::merge!) here.

Getting started with Ruby: using .each to extract information from a , Using .each to iterate over a nested hash https://ruby-doc.org/core-2.2.0/Array. html#method-i-each For this task, we go one level deeper. Arrays aren't the only Ruby type that get to see the benefits of iteration. In Ruby Collections, we learned about arrays and hashes. Hashes have several different ways of iteration -- keys, values, and both keys and values at the same time.


I recomend to use #deep_locate of hashie gem https://www.rubydoc.info/github/intridea/hashie/Hashie/Extensions/DeepLocate#deep_locate-instance_method

little bit hacky always return false not to seeking

hash.extend(Hashie::Extensions::DeepLocate)
hash.deep_locate -> (key, value, object) do 
  # what you want to do here!
  # key: hash key
  # value: hash value
  # object: hash_object
  false # prevent to stop seeking
end

Level Up Your Ruby Skillz: Working With Hashes - DEV, Last week I tackled Ruby arrays and shared some of the methods I find the most One of the easiest ways to loop over a hash is to use each . using dig . dig extracts the nested value specified by a sequence of key objects. 1 If you can't do the appropriate transformation of the structure in puppet, you can always make a custom ruby function to transform the input structure into the appropriately shaped hash/data structure to iterate over. DarylW (Jan 12 '17) If on 4.x you can also write a function in the Puppet Language (much easier).


Ruby Hashes - A Detailed Guide, Understand Ruby Hashes and common Ruby Hash methods. Mutating the Caller: The Sequel � Nested Arrays � Comparing Arrays � to_s Because hashes can have multiple elements in them, there will be times when you'll want to iterate over a Iterating over hashes is similar to iterating over arrays with some small� We use Logstash extensively within my team as our ETL engine. Things started out simple enough with log file data, but we are at a point where our primary use case is centered around Business Intelligence. All our Incident, Change, Problem, Knowledge, etc tickets are pushed through our pipelines where we perform extensive ETL to help speed things up on the reporting end. Because of the


how can fetch data from hash nested array in ruby?, Iterate over a deeply nested level of hashes in Ruby, If I understand the goal, then you should be able to pass in the parent to your save method. For the top level� In this blog post I will introduce Hash #dig_and_collect , a simple utility method that is built on top of Hash #dig to help you navigate nested hashes mixed up with arrays. Why Hash#dig is great The introduction of the Hash #dig 1 method in Ruby 2.3 completely changed the way I navigate deeply nested hashes.


Nested Array Iterator, Typical iterators in Ruby work functionally, so sometimes it's hard to make complex iterations with nested Java Two Dimensional String Array Iterator. dynamic arrays. Naive: Linear search. ndim-levels deep nested list of Python scalars. Step 1: Iterate over the first level Inside the remove_strawberry method, let's take our first dive into the contacts Hash. Then we'll use binding.pry to see where we are. We are going to first iterate over the top level of the Hash where the keys should be the person and the values should be a Hash of details about the person.