Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!usc!cs.utexas.edu!bcm!convex!newsadm From: tchrist@convex.COM (Tom Christiansen) Newsgroups: comp.lang.perl Subject: Re: Sorting an associative array by value? Message-ID: <1991Apr05.193734.20851@convex.com> Date: 5 Apr 91 19:37:34 GMT References: <1991Apr5.183701.21325@javelin.sim.es.com> Sender: newsadm@convex.com (news access account) Reply-To: tchrist@convex.COM (Tom Christiansen) Organization: CONVEX Software Development, Richardson, TX Lines: 41 Nntp-Posting-Host: pixel.convex.com From the keyboard of pashdown@javelin.sim.es.com (Pete Ashdown): :How do I go about sorting an associative array, not by the string, but by :the associated value? For example, how would I change following 'word count' :program to sort by occurance rather than alphabetically? : :foreach $word (sort keys(%wordcount)) { : printf "%20s %d\n", $word, $wordcount{$word}; :} The most straight-forward way is to declare a function that given keys, compares values. For example: sub by_value { $wordcount{$a} <=> $wordcount{$b}; } foreach $word (sort by_value keys %wordcount) { printf "%20s %d\n", $word, $wordcount{$word}; } A minor problem with this method is that the array to compare is hardcoded in. You can avoid this by using dynamic scoping. I'll also use pass-by-name for efficiency. sub _by_value { $table{$a} <=> $table{$b}; } sub sort_by_value { local(*table) = @_; sort _by_value keys %table; } foreach $word (&sort_by_value(*wordcount)) { printf "%20s %d\n", $word, $wordcount{$word}; } Another possibilty, which I don't care for as much, is to dynamically declare the &by_value function using an eval. This is left as an exercise for the reader. :-) I guess I'd better keep the sorting section in my perl tutorial after all. --tom