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

I need to sort an array of hashes based on the value of a particular key or keys of the hashes. I started to write my own function to do this, but quickly realized that

  1. This is very complicated
  2. Someone else has almost certainly already done this

So can anyone point me to the already written function that will take a reference to an array of hashes, and 1 or more key names, and will sort the array based on those keys in that order? or possibly tell me what trick of perl I'm missing that makes this an extremely simple task?

  • Comment on Sort Array of Hashes based on Hash value

Replies are listed 'Best First'.
Re: Sort Array of Hashes based on Hash value
by sean (Beadle) on Jun 07, 2000 at 03:36 UTC
    Sorting on one key is simple enough:
    @sorted = sort {$$a{"key"} <=> $$b{"key"} } @unsorted;
    To sort on more than one key, i'd probably do something like this:
    @sorted = sort {$$a{"least_signifigant_key"} <=> $$b{"least_signifigan +t_key"}} @unsorted; [...] @moresorted = sort{$$a{"most_signifigant_key"} <=> $$b{"most_signifiga +nt_key"}} @sorted;
    A function would be prettier...
    sub multi_key_sort { # pass me two references to arrays my $array = shift; # the first to the array that needs sorting.. my $keys = shift; # the second to an array of keys to sort by for my $key (@$keys) { @$array = sort {$$a{$key} cmp $$b{$key}} @$array; } return @$array; } my @sorted_array = &multi_key_sort(\@unsorted_array,\@array_of_keys); # @array_of_keys in order from least to most signifigant
    --sean
      Actually...
      sub this { my @array = @{(shift)} ; my $keys = shift ; for my $key (@$keys) { @array = sort {$$a{$key} cmp $$b{$key}} @array; } return @array; }
      would be a little cleaner. The original code would return a sorted array AND leave you with a sorted @unsorted. This way, by dereferencing the array, it will just return a sorted array, and leave @unsorted alone.
        I like the example from perlfaq4:
        Here we'll do a reverse numeric sort by value, and if two keys are identical, sort by length of key, and if that fails, by straight ASCII comparison of the keys (well, possibly modified by your locale -- see perllocale). @keys = sort { $hash{$b} <=> $hash{$a} || length($b) <=> length($a) || $a cmp $b } keys %hash;
        as our peers above have pointed out ($$a{$key}) does the work in your case, but the idea of or'ing with a final cmp will probably get better results when you can't tell what's in those arrays.

        #!/home/bbq/bin/perl
        # Trust no1!
        Awesome!
      Exactly what I was looking for!!! Wow!
Re: Sort Array of Hashes based on Hash value
by chromatic (Archbishop) on Jun 07, 2000 at 03:17 UTC
      %{array[1]} = { key1 => 3, key2 => 2, key3 => "test" }; %{array[2]} = { key1 => 2, key2 => 1, key3 => "test2" }; %{array[3]} = { key1 => 3, key2 => 1, key3 => "test3" }; %{array[4]} = { key1 => 1, key2 => 1, key3 => "test4" }; &sortarrayofhashes(\@array,"key1","key2");
      now the arrays look like this:
      # NOTE, the following is not perlcode, just statement of fact $array[1]{key1} == 1 $array[1]{key2} == 1 $array[1]{key3} == test4 $array[2]{key1} == 2 $array[2]{key2} == 1 $array[2]{key3} == test2 $array[3]{key1} == 3 $array[3]{key2} == 1 $array[3]{key3} == test3 $array[4]{key1} == 3 $array[4]{key2} == 2 $array[4]{key3} == test
      So that's the result I'm looking to be able to obtain. THnaks
RE: Sort Array of Hashes based on Hash value
by BigJoe (Curate) on Jun 07, 2000 at 03:24 UTC
    You should look at lhoward's reply to sorting hashes at this node. This should be a very good start. --Big Joe