Re: Sorting by the hash value
by DamnDirtyApe (Curate) on Jul 29, 2002 at 06:02 UTC
|
This seems to work OK for me. Can you provide some sample data for %list to illustrate what's going wrong?
print "<select name=\"m_v\">";
# %list = whats();
my %list = ( 'alpha' => 3, 'bravo' => 5, 'charlie' => 1 ) ;
sub hashValueAscendingNum {
$list{$a} <=> $list{$b};
}
foreach $key (sort hashValueAscendingNum (keys(%list))) {
print "<option value=\"$key\">$list{$key}</option>";
}
print "</select>";
Output:
<select name="m_v"><option value="charlie">1</option><option value="al
+pha">3</option><option value="bravo">5</option></select>
_______________
D
a
m
n
D
i
r
t
y
A
p
e
Home Node
|
Email
| [reply] [d/l] [select] |
Re: Sorting by the hash value
by Chady (Priest) on Jul 29, 2002 at 06:03 UTC
|
foreach my $key (
map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [$_, $list{$_}] }
keys %list ) {
...
See the Schwartzian Transform for more info.
Update: ok.. so I probably must have added the <joke> tags around ;) I figured it would be obvious... since the guy already has a subroutine to sort in. :).
He who asks will be a fool for five minutes, but he who doesn't ask will remain a fool for life.
Chady | http://chady.net/ | [reply] [d/l] |
|
|
Wow! Using a Schwartz Transform to sort a hash by value is like using a sledgehammer to crack open a peanut. The ST is not cheap, it only wins when the cost of computing the key is relatively expensive, and accessing a hash value by key is one of the cheaper things you can do in Perl. I wonder just how much slower this is?
# /usr/bin/perl -w
use strict;
use Benchmark qw/cmpthese/;
cmpthese( shift || 10_000, {
'sort' => sub { sort keys %ENV },
'sort by key' => sub { sort {$ENV{$a} cmp $ENV{$b}} keys %ENV },
'sort by ST' => sub { map { $_->[0] }
sort { $a->[1] cmp $b->[1] }
map { [$_, $ENV{$_}] } keys %ENV
},
});
__END__
% perl -w sortem 100000
Benchmark: timing 100000 iterations of sort, sort by ST, sort by key..
+.
sort: 2 wallclock secs ( 1.35 usr + 0.00 sys = 1.35 CPU) @ 73
+964.50/s (n=100000)
sort by ST: 18 wallclock secs (17.72 usr + 0.00 sys = 17.72 CPU) @ 56
+44.62/s (n=100000)
sort by key: 2 wallclock secs ( 1.34 usr + 0.00 sys = 1.34 CPU) @ 7
+4515.65/s (n=100000)
Rate sort by ST sort sort by key
sort by ST 5645/s -- -92% -92%
sort 73964/s 1210% -- -1%
sort by key 74516/s 1220% 1% --
Yep, pretty slow! (I threw the straight sort in there as well, just to give an idea of the overhead incurred by using a sort code block).
print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u' | [reply] [d/l] |
|
|
| [reply] |
Re: Sorting by the hash value
by grinder (Bishop) on Jul 29, 2002 at 06:05 UTC
|
That's odd, because the code works just fine here. Are you sure the routine whats() is returning something? Are you running the code with the -w switch? Are you sure you're not getting any errors, such as "Odd number of elements in hash assignment" or "Use of uninitialized value in concatenation (.) or string"?
One other thing about your code, if you are generating HTML, you can avoid escaping quotes (i.e., \" ) by using Perl's quoting mechanisms, such as print qq{this is a "quote"\n}. Mind you, there are better ways of generating HTML, but that's another story...
print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u' | [reply] [d/l] |
Re: Sorting by the hash value
by Juerd (Abbot) on Jul 29, 2002 at 07:23 UTC
|
| [reply] |
Re: Sorting by the hash value
by shotgunefx (Parson) on Jul 29, 2002 at 09:41 UTC
|
While this is slightly off from your question. One thing about using CGI.pm that stinks is when you provide a hash so you can have different values and labels (as you are trying to do) it doesn't sort them. If this is why you are avoiding using CGI.pm you can use the snippet below that I use. It's a simple tie that you can use to make it sort by value.
package SortHash;
#Kludge to get options sorted.
use Tie::Hash;
use vars qw(@ISA);
@ISA = qw( Tie::StdHash );
sub FIRSTKEY {
my $self = shift;
@{ $self->{_SORTHASH_KEYS} } = sort {$self->{$a} cmp $self->{$b} }
+ grep { $_ ne '_SORTHASH_KEYS' } keys %{$self};
return shift @{ $self->{_SORTHASH_KEYS} };
}
sub NEXTKEY {
my $self = shift; return shift @{ $self->{_SORTHASH_KEYS} };
}
package main;
use CGI qw(:standard);
my %list;
tie %list, 'SortHash' ; # tied hash with sorted keys by value...
print start_form;
print popup_menu(-name=>'option' , labels=> \%list, -values=> [ keys %
+list ] );
print end_form;
-Lee
"To be civilized is to deny one's nature." | [reply] [d/l] |
|
|
@keys = keys{%hash};
foreach $key (@keys)
{
$value = %hash{$key};
push(@values, $value);
}
sort(@values);
print "@values\n";
| [reply] [d/l] |
|
|
Are you replying to the root node? My kludge is to get around the fact that CGI.pm has the hash ordering (which is no order) when you use the -lables argument. I often need to use labels and tie'ing is easier than sublassing CGI.pm.
As an aside, your code is overcomplicated.
print sort values %hash;
-Lee
"To be civilized is to deny one's nature." | [reply] [d/l] |
|
|
|
|
Isn't this supposed to be:
@keys = keys{%hash};
foreach $key (@keys)
{
$value = $hash{$key}; # notice $ versus % here
push(@values, $value);
}
sort(@values);
print "@values\n";
Otherwise, I think you get an error such as:
Can't use subscript on private hash at foo.pl line 123, near "$key}"
(Did you mean $ or @ instead of %?)
BEGIN not safe after errors--compilation aborted at foo.pl line 123.
| [reply] [d/l] [select] |
|
|
Re: Sorting by the hash value
by shotgunefx (Parson) on Jul 29, 2002 at 11:17 UTC
|
sort { $list{$a} <=> $list{$b} || $list{$a} cmp $list{$b} } keys %list
or compacted...
print "<select name=m_v>\n",
( map {"\t<option name=\"$_\">$list{$_}\n" }
sort { $list{$a} <=> $list{$b} || $list{$a} cmp $list{$b} }
+ keys %list ),
'</select>';
-Lee
"To be civilized is to deny one's nature." | [reply] [d/l] |