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

hi I have a hash, %books, that looks like this:
my %books=( '34' => ['enlgish', 'dani M. rod', 54], '24' => ['spanish', 'ramk rovale', 41], '54' => ['enlgish', 'bob falicas', 17], );
I want to sort it by author's name which is where 'dani M. rod' is. how can that be done? thanks

Replies are listed 'Best First'.
Re: sorting hash by a certain value (that it is in an array)
by Corion (Patriarch) on Jul 17, 2012 at 11:28 UTC
Re: sorting hash by a certain value (that it is in an array)
by brx (Pilgrim) on Jul 17, 2012 at 11:47 UTC

    In complement to Corion's answer: Re: sorting hash by a certain value (that it is in an array)

    Here is an example. You can use more complexe sorting method (see commented line: lc(...) cmp lc(...)) and optimized it with The Orcish Maneuver.
    #!/usr/bin/env perl use strict; use warnings; my %books=( '34' => ['enlgish', 'dani M. rod', 54], '24' => ['spanish', 'ramk rovale', 41], '54' => ['enlgish', 'bob falicas', 17], ); my @sorted_books = sort { $books{$a}->[1] cmp $books{$b}->[1] #lc($books{$a}->[1]) cmp lc($books{$b}->[1]) } keys %books; print "@sorted_books";

    Update: print sorted books

    for my $book_id (@sorted_books) { print "$book_id: ",join ", ",@{ $books{$book_id} }; print "\n"; }
      this is not about sorting an array, it's about sorting an hash that has arrays in it. the example by brx created a new sorted array @sorted_books. I need the %books hash to be sorted as so:
      %books=( '54' => ['enlgish', 'bob falicas', 17], '34' => ['enlgish', 'dani M. rod', 54], '24' => ['spanish', 'ramk rovale', 41], );
      I don't see how the example by brx gives me that. when I print out the %books hash using this:
      while (my($key, $value) = each(%books)){ print "$key: $value\n"; }
      I get the same unsorted result.

        A hash is a different data structure than an array. Its advantage is that it allows arbitrary strings as keys instead of just a number. The disadvantage is that it can't be sorted. Read about "hash tables" on wikipedia if you want to know why.

        Perhaps you could use Tie::IxHash?
        my %unordered=(...); tie my %ordered, "Tie::IxHash"; for my $key (sort {$unordered{$a}[1] cmp $unordered{$b}[1]} keys %$ +unordered) { $ordered{$key}=$unordered->{$key}; };
Re: sorting hash by a certain value (that it is in an array)
by BillKSmith (Monsignor) on Jul 17, 2012 at 14:33 UTC

    I am not sure what you mean by sort it. It is not possible to sort a hash in same sense as sorting an array. You can process the contents of the hash in any order. Refer: perldoc -q "sort a hash".

    Also be warned that sorting names can be quite tricky. The following example should get you started. Note use of "Schwartzian Transformation" also described in perfaq4 under: perdoc -q "sort an array"

    use strict; use warnings; use Data::Dumper; my %books=( '34' => ['enlgish', 'dani M. rod', 54], '24' => ['spanish', 'ramk rovale', 41], '54' => ['enlgish', 'bob falicas', 17], ); my @sorted_list = map {$books{$_->[0]}} sort {lc $a->[1] cmp lc $b->[1]} map {[$_,$books{$_}[1] =~ /\b(\w+)$/]} keys %books ; print Dumper \@sorted_list;
    Update: Removed incorrect check of first names.