dbmathis has asked for the wisdom of the Perl Monks concerning the following question:

Hi All, How would I sort this hash in a hash by VAR1 keys and then VAR2 keys.

I have the following:

sub printIndex { for my $book ( sort keys %ibIndex ) { for my $keyword ( keys( %{ $ibIndex{ $book } } ) { my $pages = join( ', ', @{ $ibIndex{ $book }->{ $keyword } + } ); } } }
$VAR1 = 'Book 3'; $VAR2 = { 'wormhole' => [ 150 ], 'World Wide Web (WWW)' => [ 75, 137, 153 ], 'Wigner, Eugene P. (1902-1995)' => [ 200, 200, 203, 208 ], 'World War II (WWII)' => [ 127 ], 'Work and play' => [ 235 ] }; $VAR3 = 'Book 1'; $VAR4 = { 'wormhole' => [ 266 ], 'Whistlefield Estate' => [ 64, 73, 74, 96 ], 'wisdom' => [ 134, 140, 161, 210, 240, 58 ], 'Yost, Bill' => [ 75, 88 ], '"winners," evolutionary (see "evolution," "natural selectio +n")' => [ + 198, + 199, + 226, + 2 + ], 'Wigner, Eugene P. (1902-1995)' => [ 32 ] }; $VAR5 = 'Book 2'; $VAR6 = { 'worldview' => [ 343 ], 'wisdom' => [ 71, 130, 153, 220, 262, 265, 286, 313, 331 ], 'will' => [ 82, 117, 164 ], 'World community' => [ 344 ] };
After all this is over, all that will really have mattered is how we treated each other.

Replies are listed 'Best First'.
Re: How do I sort a hash in a hash?
by stevieb (Canon) on Apr 15, 2012 at 01:18 UTC

    If I'm understanding you correctly, adding sort when retrieving the keys of the inner hash like you do in the outer hash should do what you desire:

    sub printIndex { for my $book ( sort keys %ibIndex ) { # notice the use of sort in the next line for my $keyword ( sort keys( %{ $ibIndex{ $book } } ) { my $pages = join( ', ', @{ $ibIndex{ $book }->{ $keyword } + } ); } } }
Re: How do I sort a hash in a hash?
by AnomalousMonk (Archbishop) on Apr 15, 2012 at 05:18 UTC

    Here's a solution that sorts books numerically by book number and then case-insensitive alphabetically by the first 'word' found in the citation. You might want to use something like  \w+ or  [[:alnum:]]+ instead of  [[:alpha:]]+ in  by_first_word() if there might ever be a citation like "666, The Number of the Beast". The sorts are far from the fastest possible, but should be OK if you have no more than a few score books of a few thousand citations each. (After all, how often will you do this sort?)

    >perl -wMstrict -le "sub printIndex { my ($hr) = @_; for my $book (sort by_book_number keys %$hr) { for my $citation (sort by_first_word keys %{$hr->{$book}}) { print qq{'$book' '$citation' pgs }, join ', ', @{ $hr->{$book}{$citation} }; } } } ;; sub by_book_number { my ($an) = $a =~ m{ (\d+) }xms; my ($bn) = $b =~ m{ (\d+) }xms; return $an <=> $bn; } ;; sub by_first_word { my ($aw) = $a =~ m{ ([[:alpha:]]+) }xms; my ($bw) = $b =~ m{ ([[:alpha:]]+) }xms; return uc($aw) cmp uc($bw); } ;; my %ibIndex = ( 'Book 10' => { 'wormhole' => [ 150 ], 'World Wide Web (WWW)' => [ 75, 137, 153 ], 'Wigner, Eugene P. (1902-1995)' => [ 200, 200, 203, 208 ], 'World War II (WWII)' => [ 127 ], 'Work and play' => [ 235 ], }, 'Book 1' => { 'wormhole' => [ 266 ], 'Whistlefield Estate' => [ 64, 73, 74, 96 ], 'wisdom' => [ 134, 140, 161, 210, 240, 58 ], 'Yost, Bill' => [ 75, 88 ], '\"winners,\" evolutionary (see \"evolution,\" \"natural selectio +n\")' => [ 198, 199, 226, 2 ], 'Wigner, Eugene P. (1902-1995)' => [ 32 ], }, 'Book 2' => { 'worldview' => [ 343 ], 'wisdom' => [ 71, 130, 153, 220, 262, 265, 286, 313, 331 ], 'will' => [ 82, 117, 164 ], 'World community' => [ 344 ], }, ); ;; printIndex(\%ibIndex); " 'Book 1' 'Whistlefield Estate' pgs 64, 73, 74, 96 'Book 1' 'Wigner, Eugene P. (1902-1995)' pgs 32 'Book 1' '"winners," evolutionary (see "evolution," "natural selection +")' pgs 198, 199, 226, 2 'Book 1' 'wisdom' pgs 134, 140, 161, 210, 240, 58 'Book 1' 'wormhole' pgs 266 'Book 1' 'Yost, Bill' pgs 75, 88 'Book 2' 'will' pgs 82, 117, 164 'Book 2' 'wisdom' pgs 71, 130, 153, 220, 262, 265, 286, 313, 331 'Book 2' 'World community' pgs 344 'Book 2' 'worldview' pgs 343 'Book 10' 'Wigner, Eugene P. (1902-1995)' pgs 200, 200, 203, 208 'Book 10' 'Work and play' pgs 235 'Book 10' 'World Wide Web (WWW)' pgs 75, 137, 153 'Book 10' 'World War II (WWII)' pgs 127 'Book 10' 'wormhole' pgs 150

      Thank You! Not only did this solve my issue, I learned something new!

      After all this is over, all that will really have mattered is how we treated each other.
Re: How do I sort a hash in a hash?
by AnomalousMonk (Archbishop) on Apr 15, 2012 at 02:00 UTC

    Note that if you have Books 1 through 12, they will sort as 'Book 1', 'Book 10', 'Book 11', 'Book 12', 'Book 2', 'Book 3', ... due to the default lexic sorting of sort. Note also that '"winners," evolutionary (see "evolution," "natural selection")' sorts first in Book 1 because its first character is " (double-quote).