>>>>> "Roderick" == Roderick A Anderson <[EMAIL PROTECTED]> writes:

[from previous message]

Roderick> The problem I'm having is how to do in a one-liner the
Roderick> equivalent of this.  Getting the the $domainname_key out of
Roderick> the arrayref $domain_array.

Roderick> foreach my $row (@$domain_array) {
Roderick>     ($domainname_key, $jnk) = @$row;
Roderick> )

[from later message]

Roderick> So there is no way to do it without the foreach.  Oh well.

I *think* that the crux of your question was how to extract one column
from a [rectangular] array-of-array-refs stored in row major order.
(Is that the right term?  My FORTRAN days were a long time ago).  The
short answer is to use a 'map' (perldoc perlfunc):

   my @first_col_values = map $_->[0], @array_of_array_refs;

This will have the same effect as:

   my @first_col_values;
   foreach my $aref ( @array_of_array_refs )
   {
       push @first_col_values, $aref->[0];
   }

I find it easiest to think of 'map' (and its related sibling, 'grep')
as something that transforms one list into another list.  'map' puts
the result of each step:

| $ perl -lwe 'print join " ", map { $_*$_ } 1 .. 10;'
| 1 4 9 16 25 36 49 64 81 100

While 'grep' returns the input values for which the expression
evaluates to true:

| $ perl -lwe 'print join " ", grep { ( $_ & 1 ) == 0 } 1 .. 20;'
| 2 4 6 8 10 12 14 16 18 20

Note that 'map' evaluates it BLOCK in list context:

| $ perl -lwe 'print join " ", map { $_, $_ } 1 .. 10;'
| 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10

A classic example of this is the "Schwartzian Transform", where you
intentionally expand a simple array into an array of array refs (each
ref holding a key and the original value), which means that the
(presumably expensive key function) only gets called N times, instead
of N*log(N) times:

| my @sorted_ignoring_case = 
|   map { $_->[0] }
|     sort { $a->[1] cmp $b->[1] }
|       map { [ $_, lc($_) ] } @unsorted_mixed_case;

(Yes, "lc" is cheap, but consider "md5sum" and "@file_list", or even
trying to sort by hierarchical enumerators.)

Your case is complicated by having 0, 1, or >1 rows in the return set,
and wanting to do different things with them.  I'm not sure that I
parsed your actual question correctly, but this might be close to what
you're looking for:

| #!/usr/bin/perl -w
| 
| use strict;
| 
| sub dump_aref ( $ $ )
| {
|     my ( $label, $aref ) = @_;
| 
|     print "=== $label ===\n";
| 
|     if    ( @$aref == 0 )
|     {
|         print "no domains found\n";
|     }
|     elsif ( @$aref == 1 )
|     {
|         print "found domain: '$aref->[0][0]' (key='$aref->[0][1]')\n";
|     }
|     else
|     {
|         my $i = 0;
|         print "found ", scalar @$aref, " domains:\n",
|           map sprintf( "%3d. '%s' (key='%s')\n", ++$i, @$_ ), @$aref;
|     }
| }
| 
| dump_aref "zero results",  [];
| dump_aref "one result",    [ [ 'domain', 'key' ] ];
| dump_aref "three results", [ [ '1st domain', 'a' ],
|                              [ '2nd domain', 'b' ],
|                              [ '3rd domain', 'c' ] ];
| 
| exit 0;

Which prints:

| === zero results ===
| no domains found
| === one result ===
| found domain: 'domain' (key='key')
| === three results ===
| found 3 domains:
|   1. '1st domain' (key='a')
|   2. '2nd domain' (key='b')
|   3. '3rd domain' (key='c')

Reducing the above script to one line is left as an exercise to the
reader.  :)  Given that you seem to have different paths from this
point anyway (error on none; print and proceed on one; print and ask
user for help on >1), I don't really see the value in reducing it to
one line.

t.


Reply via email to