Search code examples
rubyhashenumerable

Lazy enumerator for nested array of hashes


Suppose I have an Array like this

data = [
  {
    key: val,
    important_key_1: { # call this the big hash
      key: val,
      important_key_2: [
        { # call this the small hash
          key: val,
        },
        {
          key: val,
        },
      ]
    },
  },
  {
    key: val,
    important_key_1: {
      key: val,
      important_key_2: [
        {
          key: val,
        },
        {
          key: val,
        },
      ]
    },
  },
]

I want to create a lazy enumerator that would return the next small hash on each #next, and move on to the next big hash and do the same when the first big hash reaches the end

The easy way to return all the internal hashes that I want would be something like this

data[:important_key_1].map do |internal_data|
  internal_data[:important_key_2]
end.flatten

Is there someway to do this or do I need to implement my own logic ?


Solution

  • This returns a lazy enumerator which iterates over all the small hashes :

    def lazy_nested_hashes(data)
      enum = Enumerator.new do |yielder|
        data.each do |internal_data|
          internal_data[:important_key_1][:important_key_2].each do |small_hash|
            yielder << small_hash
          end
        end
      end
      enum.lazy
    end
    

    With your input data and a val definition :

    @i = 0
    
    def val
      @i += 1
    end
    

    It outputs :

    puts lazy_nested_hashes(data).to_a.inspect
    #=> [{:key=>3}, {:key=>4}, {:key=>7}, {:key=>8}]
    puts lazy_nested_hashes(data).map { |x| x[:key] }.find { |k| k > 3 }
    #=> 4
    

    For the second example, the second big hash isn't considered at all (thanks to enum.lazy)