Re: Elegance, dammit!
by Util (Priest) on Jun 16, 2007 at 00:45 UTC
|
In real life, I would normally use a splice like Errto and jdporter.
Before *any* solution, I would put:
die if @ref / 3;
Most elegant, non-destructive Perl5 solution I could think of: my %out = map { $ref[$_] => [ @ref[$_+1..$_+2] ] }
grep { not $_ % 3 }
0 .. $#ref;
Even better, but requires Perl6: for @ref -> $key, $val1, $val2 {
%out{$key} = [ $val1, $val2 ];
}
Update: Better yet, this also works in Perl6: my %out = map -> $k, $v, $w {
$k => [ $v, $w ];
}, @ref;
| [reply] [d/l] [select] |
|
|
Ah-HAH! :)
(I *really* liked that Perl6 solution, BTW; I see that I'm going to have to get off my lazy butt and dig into it.)
All of that - particularly Util's solution - has finally caused a reticent neuron to fire. Originally, I thought of this:
$out{shift @ref} = [splice @ref,0,2] while @ref;
...but there's a precedence problem with that, so that %out ends up containing stuff like
2 => [ 0, 1 ],
5 => [ 3, 4 ]
etc.
so my final cut at it ends up being this:
die if @ref % 3;
$out{$a} = [splice @ref,0,2] while $a = shift @ref;
I'm definitely up for seeing more solutions, though. You folks come up with some very pretty thought patterns. :)
Thank you all!
| [reply] [d/l] [select] |
|
|
I can't resist offering a shorter Perl 6-solution:
my %out = map {$^k => [$^v, $^w]}, @ref;
The ^ secondary sigil ("twigil") is a self declaring formal paramter, all of the variables starting with $^ will be filled in the block in lexicographic order.
| [reply] [d/l] [select] |
|
|
die 'Assertion failed: @ref not divisible by 3'
if scalar @ref % 3;
If I'm not mistaken, yours dies every time @ref has any elements. | [reply] [d/l] [select] |
Re: Elegance, dammit!
by Errto (Vicar) on Jun 15, 2007 at 23:54 UTC
|
while (@array) {
my ($key, @vals) = splice @array, 0, 3;
$hash{$key} = [ @vals ];
}
assuming you no longer need the original array once you're done. | [reply] [d/l] |
Re: Elegance, dammit!
by jdporter (Paladin) on Jun 15, 2007 at 23:54 UTC
|
my @destructible = @$ref;
while ( @destructible )
{
my( $key, @val ) = splice @destructible, 0, 3;
$out{ $key } = \@val;
}
A word spoken in Mind will reach its own level, in the objective world, by its own weight
| [reply] [d/l] |
Re: Elegance, dammit!
by un-chomp (Scribe) on Jun 16, 2007 at 00:29 UTC
|
my %hoa = map { $array[$_], [ @array[ $_+1 .. $_+2 ] ] }
grep { !($_ % 3) } 0 .. $#array;
| [reply] [d/l] |
Re: Elegance, dammit!
by BrowserUk (Patriarch) on Jun 16, 2007 at 04:05 UTC
|
my @ref = map{ ("key$_", "value1_$_", "value2_$_") } 0 .. 9;;
my $i=0; $h{shift @$_}=$_ while $i < @ref and $_=[@ref[$i++,$i++,$i++]
+];;
print "$_ => @{$h{ $_ }}" for sort keys %h;;
key0 => value1_0 value2_0
key1 => value1_1 value2_1
key2 => value1_2 value2_2
key3 => value1_3 value2_3
key4 => value1_4 value2_4
key5 => value1_5 value2_5
key6 => value1_6 value2_6
key7 => value1_7 value2_7
key8 => value1_8 value2_8
key9 => value1_9 value2_9
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
Re: Elegance, dammit!
by ysth (Canon) on Jun 16, 2007 at 02:50 UTC
|
Use selectall_hashref instead, mapping the resulting HoH into a HoA if you really truly must. | [reply] |
|
|
I'm afraid that doesn't work for me, ysth. 'selectall' rather than 'selectcol' is the deal-killer here (I don't see the need for fetching the entire content of that table, extracting the columns, and then doing all this processing.)
This gets me exactly the info I need - although the structure is a little different from what I want:
my @ref = @{
$dbh->selectcol_arrayref(
"select date, label, subject from travel
where date>= curdate()-5 order by date",
{Columns=>[1,2,3]}
)
};
I do indeed appreciate your attempt to approach it from a broader viewpoint - I try not to lose track of the fact that stepping back can be as important as focusing down when trying to solve a problem. [Grin] Hell, my wife is Japanese-American. She'd beat my butt if I was ever so silly as to lose track of context.
| [reply] [d/l] |
|
|
I'm not understanding you at all. There's either something I'm missing or something you are. selectcol_arrayref and selectall_hashref will both read all the available rows. Yes, selectcol_arrayref by default throws away all but the first column, but in your invokation, you are telling it to keep all three columns.
| [reply] |
|
|
|
|
Re: Elegance, dammit!
by sfink (Deacon) on Jun 16, 2007 at 21:10 UTC
|
Purely for completeness.
Option 1:
while (@ref) {
my $k = shift(@ref);
$out{$k} = [ shift(@ref), shift(@ref) ];
}
or if the temporary bothers you:
while (@ref) {
$out{$_} = [ shift(@ref), shift(@ref) ] for shift(@ref);
}
Option 2: Change your SQL to something like SELECT key, value1, key, value2, then do:
push @{ $out{shift(@ref)} }, shift(@ref) while (@ref);
Personally, I'd stick with your original.
| [reply] [d/l] [select] |