How to get a specific output iterating a hash in Ruby?

RubyHashOutput

Ruby Problem Overview


I want to get a specific output iterating a Ruby Hash.

This is the Hash I want to iterate over:

hash = {
  1 => ['a', 'b'], 
  2 => ['c'], 
  3 => ['d', 'e', 'f', 'g'], 
  4 => ['h']
}

This is the output I would like to get:

1-----

a

b

2-----

c

3-----

d 

e

f

g

4-----

h

In Ruby, how can I get such an output with my Hash ?

Ruby Solutions


Solution 1 - Ruby

hash.each do |key, array|
  puts "#{key}-----"
  puts array
end

Regarding order I should add, that in 1.8 the items will be iterated in random order (well, actually in an order defined by Fixnum's hashing function), while in 1.9 it will be iterated in the order of the literal.

Solution 2 - Ruby

The most basic way to iterate over a hash is as follows:

hash.each do |key, value|
  puts key
  puts value
end

Solution 3 - Ruby

hash.keys.sort.each do |key|
  puts "#{key}-----"
  hash[key].each { |val| puts val }
end

Solution 4 - Ruby

Calling sort on a hash converts it into nested arrays and then sorts them by key, so all you need is this:

puts h.sort.map {|k,v| ["#{k}----"] + v}

And if you don't actually need the "----" part, it can be just:

puts h.sort

Solution 5 - Ruby

My one line solution:

hash.each { |key, array| puts "#{key}-----", array }

I think it is pretty easy to read.

Solution 6 - Ruby

You can also refine Hash::each so it will support recursive enumeration. Here is my 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 = {
	1	=>	["a", "b"], 
	2	=>	["c"], 
	3	=>	["a", "d", "f", "g"], 
	4	=>	["q"]
}

hash.each(recursive=false) do |key, value|
	puts "#{key} => #{value}"
end
# 1 => ["a", "b"]
# 2 => ["c"]
# 3 => ["a", "d", "f", "g"]
# 4 => ["q"]

Also take a look at my recursive version of Hash::merge(Hash::merge!) [here](https://stackoverflow.com/a/49139981/8410844 "@MOPO3OB's answer").

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionstsView Question on Stackoverflow
Solution 1 - Rubysepp2kView Answer on Stackoverflow
Solution 2 - RubytomascharadView Answer on Stackoverflow
Solution 3 - RubyerikView Answer on Stackoverflow
Solution 4 - Rubyglenn mcdonaldView Answer on Stackoverflow
Solution 5 - RubyElie TeyssedouView Answer on Stackoverflow
Solution 6 - RubyMOPO3OBView Answer on Stackoverflow