Don Cheadle is the best version of Captain Planet there is. I hope you’ve already seen the video. If not, go now. I’ll wait.
As it typically happens, I was creating some nested data structure and was reminded of all the different combinations that there are. For example:
- An array of arrays.
[ [1,2,3], [4,5,6] ]
- A hash of arrays.
{ :lucky => [77,42], :unlucky => [666,13] }
- An array of hashes.
[ {:cat=>"meow"}, {:dog=>"ruff"} ]
- A hash of hashes.
{ :best_in_life => {:enemies => "crushed"}, :worst => { :meatloaf => "old"} }
And I realized that I hadn’t really played with a hash of hashes much. And now I realize why. It’s really pretty useless. It’s hard to work with and the additional key really isn’t all that useful. I found it much better to just denormalize the key into the data attributes. Anyway, you can see what I mean by reading and running what’s below.
We’re going to create Captain Planet and the planeteers in a 2D hash of hashes and do some searching, iterating and other simple things. This should illustrate also how an array of hashes is a bit better. You’ll see halfway through the program we redefine the planeteers.
# search a 2d hash
def spacer(msg)
puts "\n"
puts "-" * 50
puts msg
puts "-" * 50
end
# this is not really a good data structure but we'll use it anyway.
planeteers = {
:kwame => { :element => "earth", :from => "Ghana, Africa", :actor => "LeVar Burton" },
:wheeler => { :element => "fire", :from => "Brooklyn, NY", :actor => "Joey Dedio" },
:linka => { :element => "wind", :from => "Soviet Union", :actor => "Kath Soucie" },
:gi => { :element => "water", :from => "Thailand", :actor => "Janice Kawaye" },
:ma_ti => { :element => "heart", :from => "Brazil", :actor => "Scott Menville" }
}
spacer "Here are our planeteers and their elements:"
puts planeteers.keys.collect {|p| {p => planeteers[p][:element]} }
puts "\nFind the fire planeteer:\n"
fire = planeteers.keys.collect {|p| {p => planeteers[p][:element]=="fire"} }
# => [{:kwame=>false}, {:wheeler=>true}, {:linka=>false}, {:gi=>false}, {:ma_ti=>false}]
only_fire = fire.select{|h| h.values[0] == true}
# => {:wheeler=>true}
# print just one
puts only_fire.first.keys.first
spacer "Let's do this a bit cleaner with a better data structure."
planeteers = [
{ :name => "kwame", :element => "earth", :from => "Ghana, Africa", :actor => "LeVar Burton" },
{ :name => "wheeler", :element => "fire", :from => "Brooklyn, NY", :actor => "Joey Dedio" },
{ :name => "linka", :element => "wind", :from => "Soviet Union", :actor => "Kath Soucie" },
{ :name => "gi", :element => "water", :from => "Thailand", :actor => "Janice Kawaye" },
{ :name => "ma_ti", :element => "heart", :from => "Brazil", :actor => "Scott Menville" }
]
planeteers.max_by {|p| p[:name]}
# => {:name=>"ma_ti", :element=>"heart", :from=>"Brazil", :actor=>"Scott Menville"}
planeteers.max_by {|p| p[:element]}
# => {:name=>"linka", :element=>"wind", :from=>"Soviet Union", :actor=>"Kath Soucie"}
puts "Find the heart planeteer:"
puts planeteers.select {|p| p[:element] == "heart" }.first[:name]
# first we'll put a fake planeteer on the end for cpt planet
planeteers << { :name => "all", :element => "go planet" }
spacer "Let's summon Captain Planet!"
planeteers.each do |planeteer|
puts "#{planeteer[:name].capitalize}: #{planeteer[:element].capitalize}!"
end
# pop off fake guy
planeteers.pop
Here’s what it spits out:
-------------------------------------------------- Here are our planeteers and their elements: -------------------------------------------------- {:kwame=>"earth"} {:wheeler=>"fire"} {:linka=>"wind"} {:gi=>"water"} {:ma_ti=>"heart"} Find the fire planeteer: wheeler -------------------------------------------------- Let's do this a bit cleaner with a better data structure. -------------------------------------------------- Find the heart planeteer: ma_ti -------------------------------------------------- Let's summon Captain Planet! -------------------------------------------------- Kwame: Earth! Wheeler: Fire! Linka: Wind! Gi: Water! Ma_ti: Heart! All: Go planet!