>>>>> "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.