CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
Sorting a hash?

 



Tim
Deleted

Mar 22, 2000, 10:35 PM

Post #1 of 5 (1259 views)
Sorting a hash? Can't Post

Hi,

I'd like the output to be alphabetical:

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>


foreach $cat (keys %categories) {
while ($categories{$cat} =~ /\n/) {
$categories{$cat} =~ s/\n//;
}
print "<option value=\"$categories{$cat}\">$categories{$cat}</option>";
}
</pre><HR></BLOCKQUOTE>

I tried this but it didn't work:

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>


foreach $cat (sort (keys(%categories))) {
while ($categories{$cat} =~ /\n/) {
$categories{$cat} =~ s/\n//;
}
print "<option value=\"$categories{$cat}\">$categories{$cat}</option>";
}
</pre><HR></BLOCKQUOTE>

Any help would be appreciated.

Tim


japhy
Enthusiast

Mar 23, 2000, 11:47 AM

Post #2 of 5 (1259 views)
Re: Sorting a hash? [In reply to] Can't Post

sort() defaults to ASCIIbetical order -- that is, by the value of a character in ASCII. "0" has a value of 48, "A" has a value of 65, and "a" has a value of 97. Thus, any string starting with "A" is sorted in front a string starting with "a". That also means that any string starting with "Z" is sorted in front of a string starting with "a". Example:

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>


sort (1, 2, 5, 10, 23) => (1, 10, 2, 23, 5)
sort ("Zoo", "axe", 4) => (4, "Zoo", "axe")
</pre><HR></BLOCKQUOTE>

If you want to sort such that "Z" comes after "a", then you need to do sort case-insensitively:

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>


# method 1
@sorted = sort { lc($a) cmp lc($b) } @list;
</pre><HR></BLOCKQUOTE>

This tells sort() to compare its arguments via their lowercase representation. It can be a bit slow, though, because for a big list, it evaluates lc($a) and lc($b) many times. The next example, a Schwartzian transform, uses references to speed things up:

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>


# method 2; Schwartzian transform
@sorted =
map { $_->[1] } # the original string
sort { $a->[0] cmp $b->[0] } # the lc() string
map { [ lc($_), $_ ] } # [ lowercase, original ]
@list;
</pre><HR></BLOCKQUOTE>

You can do even better, though, by using a Guttman-Rosler transform, which is good because it uses string tricks so that you DON'T pass any code to the sort() function, so you use Perl's internal sort(), which is a good thing:

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>


# method 3; Guttman-Rosler transform
@sorted =
map { substr($_, length($_)/2) } # second half of string (original string)
sort
map { lc($_) . $_ } # lowercase in front of original
@list;
</pre><HR></BLOCKQUOTE>

I hope this helps you out. It was fun for me to write this. Smile

[This message has been edited by japhy (edited 03-23-2000).]


Tim
Deleted

Mar 23, 2000, 12:06 PM

Post #3 of 5 (1259 views)
Re: Sorting a hash? [In reply to] Can't Post

Hi,

Thanks. That was very informative. One more question....

What would I change my code to?

I'm not sure how to proceed from here.

Thanks,

Tim


dws
Deleted

Mar 23, 2000, 2:57 PM

Post #4 of 5 (1259 views)
Re: Sorting a hash? [In reply to] Can't Post

Interesting transform, though it won't correctly sort all cases. Consider qw(foo Food). The sort sees qw(foofoo foodFood), and thus the transform thinks "Food" preceeds "foo".




japhy
Enthusiast

Mar 23, 2000, 3:19 PM

Post #5 of 5 (1259 views)
Re: Sorting a hash? [In reply to] Can't Post

Whoa. Damn. Nice catch. Bonus points to you, dws.

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives