Sync perlfaq.
[p5sagit/p5-mst-13.2.git] / pod / perlfaq4.pod
index 179681b..22ea1ae 100644 (file)
@@ -1,6 +1,6 @@
 =head1 NAME
 
-perlfaq4 - Data Manipulation ($Revision: 1.69 $, $Date: 2005/10/14 15:34:06 $)
+perlfaq4 - Data Manipulation ($Revision: 1.73 $, $Date: 2005/12/31 00:54:37 $)
 
 =head1 DESCRIPTION
 
@@ -392,7 +392,7 @@ integers (inclusive), For example: C<random_int_in(50,120)>.
 The localtime function returns the day of the year.  Without an
 argument localtime uses the current time.
 
-    $day_of_year = (localtime)[7];
+       $day_of_year = (localtime)[7];
 
 The POSIX module can also format a date as the day of the year or
 week of the year.
@@ -484,20 +484,20 @@ Use one of the Date modules. The C<DateTime> module makes it simple, and
 give you the same time of day, only the day before.
 
        use DateTime;
-       
+
        my $yesterday = DateTime->now->subtract( days => 1 );
-       
+
        print "Yesterday was $yesterday\n";
 
 You can also use the C<Date::Calc> module using its Today_and_Now
 function.
 
        use Date::Calc qw( Today_and_Now Add_Delta_DHMS );
-       
+
        my @date_time = Add_Delta_DHMS( Today_and_Now(), -1, 0, 0, 0 );
-       
+
        print "@date\n";
-       
+
 Most people try to use the time rather than the calendar to figure out
 dates, but that assumes that days are twenty-four hours each.  For
 most people, there are two days a year when they aren't: the switch to
@@ -589,11 +589,11 @@ does not show up next to itself
 
 This is documented in L<perlref>, and although it's not the easiest
 thing to read, it does work. In each of these examples, we call the
-function inside the braces of used to dereference a reference. If we
+function inside the braces used to dereference a reference. If we
 have a more than one return value, we can construct and dereference an
 anonymous array. In this case, we call the function in list context.
 
-    print "The time values are @{ [localtime] }.\n";
+       print "The time values are @{ [localtime] }.\n";
 
 If we want to call the function in scalar context, we have to do a bit
 more work. We can really have any code we like inside the braces, so
@@ -601,18 +601,26 @@ we simply have to end with the scalar reference, although how you do
 that is up to you, and you can use code inside the braces.
 
        print "The time is ${\(scalar localtime)}.\n"
-       
+
        print "The time is ${ my $x = localtime; \$x }.\n";
-       
+
 If your function already returns a reference, you don't need to create
 the reference yourself.
 
        sub timestamp { my $t = localtime; \$t }
-       
+
        print "The time is ${ timestamp() }.\n";
-       
-In most cases, it is probably easier to simply use string
-concatenation, which also forces scalar context.
+
+The C<Interpolation> module can also do a lot of magic for you. You can
+specify a variable name, in this case C<E>, to set up a tied hash that
+does the interpolation for you. It has several other methods to do this
+as well.
+
+       use Interpolation E => 'eval';
+       print "The time values are $E{localtime()}.\n";
+
+In most cases, it is probably easier to simply use string concatenation,
+which also forces scalar context.
 
        print "The time is " . localtime . ".\n";
 
@@ -1277,7 +1285,7 @@ If you want to actually extract the matching elements, simply use grep in
 list context.
 
        my @matches = grep $_ eq $whatever, @array;
-       
+
 =head2 How do I compute the difference of two arrays?  How do I compute the intersection of two arrays?
 
 Use a hash.  Here's code to do both and more.  It assumes that
@@ -1786,27 +1794,50 @@ such as each().
 
 =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:
+(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.
 
-    @keys = sort keys %hash;   # sorted by key
-    @keys = sort {
-                   $hash{$a} cmp $hash{$b}
-           } keys %hash;       # and by value
+       my @keys = sort { $hash{$a} <=> $hash{$b} } keys %hash;
 
-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>).
+From there we can get more complex. If the hash values are the same,
+we can provide a secondary sort on the hash key.
 
-    @keys = sort {
-               $hash{$b} <=> $hash{$a}
-                         ||
-               length($b) <=> length($a)
-                         ||
-                     $a cmp $b
-    } keys %hash;
+       my @keys = sort {
+               $hash{$a} <=> $hash{$b}
+                       or
+               "\L$a" cmp "\L$b"
+               } keys %hash;
 
 =head2 How can I always keep my hash sorted?
 
@@ -2124,7 +2155,7 @@ the PDL module from CPAN instead--it makes number-crunching easy.
 
 =head1 AUTHOR AND COPYRIGHT
 
-Copyright (c) 1997-2005 Tom Christiansen, Nathan Torkington, and
+Copyright (c) 1997-2006 Tom Christiansen, Nathan Torkington, and
 other authors as noted. All rights reserved.
 
 This documentation is free; you can redistribute it and/or modify it