I find these kinds of data structures are hard to get a handle on, so I decided to use some data that I was familiar with. Here is a very small collection of some of my music collection.
This particular structure is a hash of hashes.
Paste this into a new Perl script:
#! /usr/bin/perl use strict; use warnings; my ($artist,$cd,$tracknum,$track,%music); my $Andx=1; #artist index my $Cndx=1; #CD index %music = ( "Aural Float" => { "Freefloat" => { "01" => "Perspectives", "02" => "Freefloat", "03" => "Switchin' The Wave Of Thought", "04" => "Soulsearching", "05" => "Travelogue", "06" => "At The Crossroads", "07" => "New Frontiers", "08" => "Zwei G", "09" => "Session 5", "10" => "AF Study II", "11" => "Switchin' The Wave Of Thought (Reprise)", }, "Beautiful Someday" => { "01" => "How Deep", "02" => "Dreamer's Dream", "03" => "Him & Her", "04" => "Interlude I", "05" => "Beautiful Someday", "06" => "Gone Forever", "07" => "Still Here", "08" => "Simplicity", "09" => "Interlude II", "10" => "I Adore You", "11" => "Männerwirtschaft", "12" => "Be As You Are", "13" => "Interlude III", "14" => "Life In Dub", }, }, );
In this example, 'Aural Float' is a key to two values: 'Freefloat' and 'Beautiful Someday'.
They in turn are each keys to a hash of track numbers, which are keys to track names (values).
To print a list (sorted by artist and CD) ...
foreach $artist (sort keys (%music)) { print "$Andx $artist\n"; $Andx++; foreach $cd (sort keys $music{$artist}) { print "\t$Cndx $cd\n"; $Cndx++; foreach $tracknum (sort keys $music{$artist}{$cd}) { print "\t\t$tracknum $music{$artist}{$cd}{$tracknum}\n"; } } }
Very nice, we've even added a counter for artist, and their CDs.
But can you search for something?
print "Do you have anything by 'Aural Float'?\n"; if (exists($music{"Aural Float"})) { print "Yes I do:\n" ; for $cd (sort keys $music{'Aural Float'} ) { print "\t $cd\n"; $cdSaved=$cd; } }
Great ... "What are the tracks on 'Freefloat'?"
$cd = "Freefloat"; print "What are the tracks on '$cd'?\n"; foreach $artist (keys %music) { foreach $tracknum (sort keys $music{$artist}{$cd}) { print "$tracknum $music{$artist}{$cd}{$tracknum}\n"; } }
Finally, can you search for a track by an artist?
This one is a little tricky, because now we need to search for a value not a key. We can't use exists for this, since that only looks for keys.
my $query = "Interlude II"; # comment this line & uncomment next line to try 'unfound' #my $query = "0asdf09a8dsI"; # uncomment this line & comment previous line to try 'unfound' $artist = "Aural Float"; my $found; print "Do you have '$query' by '$artist'?\n"; foreach $cd (keys $music{$artist}) { foreach $tracknum (keys $music{$artist}{$cd}) { if ($query eq $music{$artist}{$cd}{$tracknum}) { # use 'eq' instead of '=~' to match exact track $found=1; print "Yes, it's on '$cd', track $tracknum\n" if ($found==1); } else { $found=0; } } } print "Not found.\n" if (! $found);
We've used variables to hold our search item and artist - they can be used just like a literal string in the search code.
We've also used eq instead of the match operator =~ because there are other tracks that are similar to our query, but only 1 exact match.
I hope with these examples you can begin to see the power of hashes.
Next, what else can we do with hashes?