Printing a Hash

Credit: Ben Giddings

Problem

You want to print out the contents of a Hash, but Kernel#puts doesn't give very useful results.

h = {} h[:name] = "Robert" h[:nickname] = "Bob" h[:age] = 43 h[:email_addresses] = {:home => "bob@example.com", :work => "robert@example.com"} h # => {:email_addresses=>["bob@example.com", "robert@example.com"], # :nickname=>"Bob", :name=>"Robert", :age=>43} puts h # nicknameBobage43nameRobertemail_addresseshomebob@example.comworkrobert@example.com puts h[:email_addresses] # homebob@example.comworkrobert@example.com

 

Solution

In other recipes, we sometimes reformat the results or output of Ruby statements so they'll look better on the printed page. In this recipe, you'll see raw, unretouched output, so you can compare different ways of printing hashes.

The easiest way to print a hash is to use Kernel#p. Kernel#p prints out the "inspected" version of its arguments: the string you get by calling inspect on the hash. The "inspected" version of an object often looks like Ruby source code for creating the object, so it's usually readable:

p h[:email_addresses] # {:home=>"bob@example.com", :work=>"robert@example.com"}

For small hashes intended for manual inspection, this may be all you need. However, there are two difficulties. One is that Kernel#p only prints to stdout. The second is that the printed version contains no newlines, making it difficult to read large hashes.

p h # {:nickname=>"Bob", :age=>43, :name=>"Robert", :email_addresses=>{:home=> # "bob@example.com", :work=>"robert@example.com"}}

When the hash you're trying to print is too large, the pp ("pretty-print") module produces very readable results:

require ' pp' pp h[:email_addresses] # {:home=>"bob@example.com", :work=>"robert@example.com"} pp h # {:email_addresses=>{:home=>"bob@example.com", :work=>"robert@example.com"} # :nickname=>"Bob", # :name=>"Robert", # :age=>43}

 

Discussion

There are a number of ways of printing hash contents. The solution you choose depends on the complexity of the hash you're trying to print, where you're trying to print the hash, and your personal preferences. The best general-purpose solution is the pp library.

When a given hash element is too big to fit on one line, pp knows to put it on multiple lines. Not only that, but (as with Hash#inspect), the output is valid Ruby syntax for creating the hash: you can copy and paste it directly into a Ruby program to recreate the hash.

The pp library can also pretty-print to I/O streams besides standard output, and can print to shorter lines (the default line length is 79). This example prints the hash to $stderr and wraps at column 50:

PP::pp(h, $stderr, 50) # {:nickname=>"Bob", # :email_addresses=> # {:home=>"bob@example.com", # :work=>"robert@example.com"}, # :age=>43, # :name=>"Robert"} # => #

You can also print hashes by converting them into YAML with the yaml library. YAML is a human-readable markup language for describing data structures:

require 'yaml' puts h.to_yaml # -- # :nickname: Bob # :age: 43 # :name: Robert # :email_addresses: # :home: bob@example.com # :work: robert@example.com

If none of these is suitable, you can print the hash out yourself by using Hash#each_pair to iterate over the hash elements:

h[:email_addresses].each_pair do |key, val| puts "#{key} => #{val}" end # home => bob@example.com # work => robert@example.com

 

See Also

Категории