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

How do I sort an associative array? (indexes are strings)

Edited by castaway lc(.*)

Replies are listed 'Best First'.
Re: SORT ASSOC ARRAY
by Ovid (Cardinal) on Oct 09, 2003 at 18:23 UTC

    A few pointers:

    • Typing in ALL CAPS is considered impolite.
    • Associative arrays in Perl are now more commonly known as hashes.
    • The keys in hashes are always strings, so the question is whether or not you want it sorted numerically (I'm assuming 'no')
    • And welcome to Perlmonks :) Have fun!

    How do you plan to use this? Hashes are inherently unsorted and, therefore, sorting them is useless. Sorting their data and using the output of the sort, however, is quite useful:

    foreach my $key (sort keys %hash) { print "$key $hash{$key}\n"; }

    Cheers,
    Ovid

    New address of my CGI Course.

Re: How do I sort an associative array?
by davido (Cardinal) on Oct 09, 2003 at 18:46 UTC
    Associative arrays (ie, hashes) are destined to always being unsorted unless you tie them. But that carries with it serious limitations. The best solution is usually to not care what order the hash's elements are in, but rather, iterate over its keys in a sorted order. Sorting the keys is as simple as:
    my @sorted = sort keys %hash;
    Or in the context of a loop:
    foreach my $key (sort keys %hash) { # Do something with $hash{key}; }

    You can also sort the keys by the value they point to...

    my @sortedkeys = sort { $hash{$a} cmp $hash{$b} } keys %hash;

    The point is, that you pretty much want to think in terms of unsorted hashes with (when needed) a list of sorted keys.

    See sort, and perldata.


    Dave


    "If I had my life to do over again, I'd be a plumber." -- Albert Einstein
Re: SORT ASSOC ARRAY
by BrowserUk (Patriarch) on Oct 09, 2003 at 19:21 UTC

    One addition to the preceding good advice. If you find yourself having to re-sort the same(sup>1*) hash more than once in your code, a useful optimisation is to keep an array that contains the keys in their sorted order and use that the second and subsequent times.

    my %hash = ( your => 1, data => 2, goes = 3, here => 4 ); my @sorted_keys = sort keys %hash; for( @sort_keys ) { print $hash{ $_ }; }

    1 If you only change the values, ten you can re-use @sorted_keys ok, but if you add or delete keys to/from %hash, then @sorted_keys would need to be regenerated. This is only of real benefit if

    • Your keys never change.
    • Your hash is very large.

    For small hashes, or those where the keys are constantly changing, or if your only iterating the hash once, this idea is best forgotten :)


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail

Re: SORT ASSOC ARRAY
by ChrisR (Hermit) on Oct 09, 2003 at 18:58 UTC
    Or to sort on the keys numerically:
    for my $x(sort {return $a <=> $b} keys %hash) { print "$x = $hash{$x}\n"; }
Re: SORT ASSOC ARRAY
by snax (Hermit) on Oct 09, 2003 at 20:24 UTC
    Like ChrisR above, but this will let you get the values sorted.

    First, numerically:

    for my $x(sort {return $hash{$a} <=> $hash{$b}} keys %hash) { print "$x = $hash{$x}\n"; }
    and now lexicographically
    for my $x(sort {return $hash{$a} cmp $hash{$b}} keys %hash) { print "$x = $hash{$x}\n"; }
Re: SORT ASSOC ARRAY
by diotalevi (Canon) on Oct 09, 2003 at 19:19 UTC
      Thanks much. And sorry 'bout them CAPS!! Ron rowhiteny