cvs commit: perlfaq perlfaq4.pod perlfaq5.pod
[email protected] (brian d foy) 27 Oct 2005 20:27:31 -0000
| Newsgroups | perl.cvs.perlfaq |
|---|---|
| Message-ID | <[email protected]> |
cvsuser 05/10/27 13:27:30
Modified: . perlfaq4.pod perlfaq5.pod
Log:
* perlfaq4: How do I sort a hash (optionally by value instead of key)?
+ I completely replaced the answer to disambiguate the "sort key"
and "hash key"
* perlfaq5: How do I get a file's timestamp in perl?
+ re-ordered the file test operators to parallel their mentions
in the prose
Revision Changes Path
1.70 +45 -22 perlfaq/perlfaq4.pod
Index: perlfaq4.pod
===================================================================
RCS file: /cvs/public/perlfaq/perlfaq4.pod,v
retrieving revision 1.69
retrieving revision 1.70
diff -u -r1.69 -r1.70
--- perlfaq4.pod 14 Oct 2005 15:34:06 -0000 1.69
+++ perlfaq4.pod 27 Oct 2005 20:27:30 -0000 1.70
@@ -1786,27 +1786,50 @@
=head2 How do I sort a hash (optionally by value instead of key)?
-Internally, hashes are stored in a way that prevents you from imposing
-an order on key-value pairs. Instead, you have to sort a list of the
-keys or values:
-
- @keys = sort keys %hash; # sorted by key
- @keys = sort {
- $hash{$a} cmp $hash{$b}
- } keys %hash; # and by value
-
-Here we'll do a reverse numeric sort by value, and if two keys are
-identical, sort by length of key, or if that fails, by straight ASCII
-comparison of the keys (well, possibly modified by your locale--see
-L<perllocale>).
-
- @keys = sort {
- $hash{$b} <=> $hash{$a}
- ||
- length($b) <=> length($a)
- ||
- $a cmp $b
- } keys %hash;
+(contributed by brian d foy)
+
+To sort a hash, start with the keys. In this example, we give the list of
+keys to the sort function which then compares them ASCIIbetically (which
+might be affected by your locale settings). The output list has the keys
+in ASCIIbetical order. Once we have the keys, we can go through them to
+create a report which lists the keys in ASCIIbetical order.
+
+ my @keys = sort { $a cmp $b } keys %hash;
+
+ foreach my $key ( @keys )
+ {
+ printf "%-20s %6d\n", $key, $hash{$value};
+ }
+
+We could get more fancy in the C<sort()> block though. Instead of
+comparing the keys, we can compute a value with them and use that
+value as the comparison.
+
+For instance, to make our report order case-insensitive, we use
+the C<\L> sequence in a double-quoted string to make everything
+lowercase. The C<sort()> block then compares the lowercased
+values to determine in which order to put the keys.
+
+ my @keys = sort { "\L$a" cmp "\L$b" } keys %hash;
+
+Note: if the computation is expensive or the hash has many elements,
+you may want to look at the Schwartzian Transform to cache the
+computation results.
+
+If we want to sort by the hash value instead, we use the hash key
+to look it up. We still get out a list of keys, but this time they
+are ordered by their value.
+
+ my @keys = sort { $hash{$a} <=> $hash{$b} } keys %hash;
+
+From there we can get more complex. If the hash values are the same,
+we can provide a secondary sort on the hash key.
+
+ my @keys = sort {
+ $hash{$a} <=> $hash{$b}
+ or
+ "\L$a" cmp "\L$b"
+ } keys %hash;
=head2 How can I always keep my hash sorted?
1.39 +2 -2 perlfaq/perlfaq5.pod
Index: perlfaq5.pod
===================================================================
RCS file: /cvs/public/perlfaq/perlfaq5.pod,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -r1.38 -r1.39
--- perlfaq5.pod 13 Oct 2005 19:49:13 -0000 1.38
+++ perlfaq5.pod 27 Oct 2005 20:27:30 -0000 1.39
@@ -687,7 +687,7 @@
If you want to retrieve the time at which the file was last
read, written, or had its meta-data (owner, etc) changed,
-you use the B<-M>, B<-A>, or B<-C> file test operations as
+you use the B<-A>, B<-M>, or B<-C> file test operations as
documented in L<perlfunc>. These retrieve the age of the
file (measured against the start-time of your program) in
days as a floating point number. Some platforms may not have