Re: sorting hashes by value
by samtregar (Abbot) on Nov 08, 2002 at 21:20 UTC
|
Do you want to sort the values or sort the keys by their values? I suspect the latter. Here's how to get a list of words sorted by value:
@words = sort { $word_list{$a} <=> $word_list{$b} } keys %word_list;
This works because keys() returns a list of keys for the %word_list hash. Then the sort block compares these keys by looking up their value in %word_list. The return from sort is the list of keys sorted by their values.
If you really wanted a list of sorted values, that's just:
@values = sort values %word_list;
-sam
| [reply] [d/l] [select] |
|
|
Thanks! so when its sorted into @words does it keep the word and the value? So in order for me to print it do I
for $i (0.. $#words_list){
for $words (keys %{$words[$i]}){
print "word $i = $words\n";
}
}
?? | [reply] [d/l] |
|
|
No, that won't work. If you need to keep the values along with the keys you can build it into the sort:
@pairs = sort { $a->[1] <=> $b->[1] }
map { [ $_ => $word_list{$_} ] }
keys %word_list;
print "word $_->[0] = $_->[1]\n" for @pairs;
This works by building up a list of two-element arrays using map. The first element is the key and the second element is the value. Then sort is used to sort them by the second element. The return value is a list of two-element arrays, sorted by their second element.
You might recognize this as the tail of a Schwartzian Transform.
-sam
| [reply] [d/l] |
|
|
|
|
|
|
@words = sort { $word_list{$a} <=> $word_list{$b} } keys %word_list;
foreach $word (@words) {
print "word $word = $word_list{$word}\n";
}
@words is already a sorted list of the keys in %word_list. Of course, this assumes that nobody is doing pesky things like adding to %word_list between the time you sorted it and the time you decided to print it.
| [reply] [d/l] |
Re: sorting hashes by value
by Zaxo (Archbishop) on Nov 08, 2002 at 21:22 UTC
|
You're near, but if you want to get keys out, you need to put keys in:
@keys = sort {
$word_list{$a} <=> $word_list{$b}
} keys %word_list;
After Compline, Zaxo | [reply] [d/l] |
|
|
To print the values with the words...would it be...
@keysorted = sort {$word_list{$b} <=> $word_list{$a}} keys %word_list;
for $i (0..$#keysorted){
for $word(keys %{$keysorted[$i]}){
pritn "$word = $keys[$i]{word}\n";
| [reply] [d/l] |
|
|
There's an easier way to do it:
foreach my $key (
sort { $word_list{$b} <=> $word_list{$a} }
keys %word_list ) {
print $key, " ", $word_list{$key}, "\n";
}
| [reply] [d/l] |
Re: sorting hashes by value
by waswas-fng (Curate) on Nov 08, 2002 at 21:22 UTC
|
@orderedkeys = sort {$hashname{"$a"} <=> $hashname{"$b"} } keys %hashname;
-Waswas | [reply] [d/l] |
Re: sorting hashes by value
by Theseus (Pilgrim) on Nov 08, 2002 at 22:33 UTC
|
Could the Schwartzian Transform be applied to this problem? I'm definitely not the one to write the code for you(way too unfamiliar with the inner workings of the ST for me to start recommending how others should use it), but if I'm not mistaken as to its purpose, it seems like it would work for this application. | [reply] |
|
|
The Schwartzian Transform would work for this application, just like it would for any sort. It is a replacement for a normal sort which trades memory space for speed. For example, imagine you need to sort by the foozle() of each member of a list. You could do it the easy way:
@result = sort { foozle($a) <=> foozle($b) } @list;
But the problem is that foozle() will be called multiple times for each item being sorted. If foozle() is a slow function then you'll be wasting a lot of time. The Schwartzian transform works by building up a temporary data structure than contains the value and the foozle() of that value. Example:
@result = map { $_->[1] }
sort { $a->[0] <=> $b->[0] }
map { [ foozle($_), $_ ] }
@list;
However, in this case the "foozle()" is just a hash lookup. Hash lookups are so fast that an ST is probably more expensive than a simple sort.
-sam
| [reply] [d/l] [select] |
Re: sorting hashes by value
by data67 (Monk) on Nov 09, 2002 at 07:13 UTC
|
Just a reminder, that Data::Dumper is your friend for stuff like this.
Goooo Juve! | [reply] |
Re: sorting hashes by value
by Anonymous Monk on Nov 10, 2002 at 01:19 UTC
|
You got lots of replies already, one more comment is that, you can either sort the entities as numbers or characters. the order would be different, for example, if you have a list:
@a = (2, 10, 1);
sort {$a <=> $b} @a would give you (1, 2, 10), when
sort {$a cmp $b} @a will give you (1, 10, 2)
the second one is the default. | [reply] [d/l] |
|
|
Another basic thing about sort you might want to know is that, you can determining the sroting order simply by the oder of $a and $b.
If you have
@a = (1,3,2);
sort {$a <=> $b} gives you (1,2,3), when
sort {$b <=> $a} gives you (3,2,1)
| [reply] [d/l] |