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

Hi

I have an array of hashes that looks like this:

({doc1=>2345}, {doc2=>1234}, {doc3=>5678}, {doc4=>4567})

I would like to sort this array of hashes by the values of the keys so that I end up with an array that looks like this:

(doc2, doc1, doc4, doc3)

Help!

Thanks in advance

Campbell

PS: I know that this is similar to a question that has been asked already, but that was to do with hashes that have multiple keys.
I hope, therefore, that the answer to my question will be simpler

  • Comment on sorting an array of hashes by the value of the keys

Replies are listed 'Best First'.
Re: sorting an array of hashes by the value of the keys
by broquaint (Abbot) on Jun 19, 2003 at 15:11 UTC
    This will work for hashes with single keys
    use Data::Dumper; my @aoh = ({doc1=>2345}, {doc2=>1234}, {doc3=>5678}, {doc4=>4567}); my @sorted_aoh = sort { (%$a)[1] <=> (%$b)[1] } @aoh; print Dumper \@sorted_aoh; __output__ $VAR1 = [ { 'doc2' => 1234 }, { 'doc1' => 2345 }, { 'doc4' => 4567 }, { 'doc3' => 5678 } ];

    HTH

    _________
    broquaint

      I'll just expand on this so that it sorts on the key that starts with "doc" and ends with a number. This removes the "there must be only one key" requirement.

      my @sorted_aoh = sort { (map /^doc(\d+)/ ? 0+$1 : (), keys(%$a))[0] <=> (map /^doc(\d+)/ ? 0+$1 : (), keys(%$b))[0] } @aoh;

      That happens to be suboptimal because every comparison is doing a potentially expensive operation to each hash. An improvement would be to use a Guttman-Rossler transform and then you get something really slick.

      my @sorted_aoh = map $aoh[ substr $_, 5 ], sort map { # Retrieve the document number my $doc_key = (map /^doc(\d+)$/ ? 0 + $1 : (), keys %{$aoh[$_]})[0 +]; # Return the document number, a null and the original array index pack( 'N', $doc_key ) . "\0" . $_; } 0 .. $#aoh
Re: sorting an array of hashes by the value of the keys
by artist (Parson) on Jun 19, 2003 at 15:13 UTC
    use strict; use warnings; my %hash = ( doc1 => 2345, doc2 => 1234, doc3 => 5678, doc4 => 4567, ); my @sorted_docs = sort { $hash{$a} <=> $hash{$b} } keys %hash; print join " " => @sorted_docs;

    artist

Re: sorting an array of hashes by the value of the keys
by Mr. Muskrat (Canon) on Jun 19, 2003 at 15:22 UTC

    Yet another way to do it...

    my @array = ({doc1=>2345}, {doc2=>1234}, {doc3=>5678}, {doc4=>4567}); my %hash = map { %{$_} } @array; my @sorted = sort { $hash{$a} <=> $hash{$b} } keys %hash; print "@sorted\n";

    Update: Removed each from my %hash = map { each %{$_} } @array;.

Re: sorting an array of hashes by the value of the keys
by Bilbo (Pilgrim) on Jun 19, 2003 at 15:21 UTC

    Is there a good reason why you want an array of hashes each containing a single value? I would have thought that either a single hash or an array of two element arrays might be more appropriate.

    For example:

    my %hash = (doc1 => 2345, doc2 => 1234, doc3 => 5678, doc4 => 4567);

    You could then get a list of the keys that you wanted in the right order with

    my @keys = sort {$hash{$a} <=> $hash{$b} }(keys %hash);

    or an array of two element arrays:

    my @array = (["doc1", 2345], ["doc2", 1234], ["doc3", 5678], ["doc4", 4567]);

    In this case you would sort the array with:

    my @sorted = sort {$a->[1] <=> $b->[1]} @array;

Re: sorting an array of hashes by the value of the keys
by campbell (Beadle) on Jun 20, 2003 at 08:30 UTC
    Thanks, folks

    Campbell