How do I sort an associative array by value instead of by key?


    You have to declare a sort subroutine to do this.  Let's assume
    you want an ASCII sort on the values of the associative array %ary.
    You could do so this way:

        foreach $key (sort by_value keys %ary) {
            print $key, '=', $ary{$key}, "\n";
        } 
        sub by_value { $ary{$a} cmp $ary{$b}; }

    If you wanted a descending numeric sort, you could do this:

        sub by_value { $ary{$b} <=> $ary{$a}; }

    You can also inline your sort function, like this, at least if 
    you have a relatively recent patchlevel of perl4:

        foreach $key ( sort { $ary{$b} <=> $ary{$a} } keys %ary ) {
            print $key, '=', $ary{$key}, "\n";
        } 

    If you wanted a function that didn't have the array name hard-wired
    into it, you could so this:

        foreach $key (&sort_by_value(*ary)) {
            print $key, '=', $ary{$key}, "\n";
        } 
        sub sort_by_value {
            local(*x) = @_;
            sub _by_value { $x{$a} cmp $x{$b}; } 
            sort _by_value keys %x;
        } 

    If you want neither an alphabetic nor a numeric sort, then you'll 
    have to code in your own logic instead of relying on the built-in
    signed comparison operators "cmp" and "<=>".

    Note that if you're sorting on just a part of the value, such as a
    piece you might extract via split, unpack, pattern-matching, or
    substr, then rather than performing that operation inside your sort
    routine on each call to it, it is significantly more efficient to
    build a parallel array of just those portions you're sorting on, sort
    the indices of this parallel array, and then to subscript your original
    array using the newly sorted indices.  This method works on both
    regular and associative arrays, since both @ary[@idx] and @ary{@idx}
    make sense.  See page 245 in the Camel Book on "Sorting an Array by a
    Computable Field" for a simple example of this.