Recently having had the need to turn a CSV file into an array of arrays,
I came up with what I think is a clever, non-Text::CSV, solution.
And, as a bonus, it uses an (I think) uncommon array variable
in the for loop.
What do you think?
use warnings;
use strict;
my @AoA;
foreach ( <DATA> )
{
for ( my @i = split( /\s+/ ); $#i >= 0; )
{
unless ( defined( $AoA[ $#i ] ) )
{ $AoA[ $#i ] = [ ]; }
push @{ $AoA[ $#i ] } , pop( @i );
};
}
print join( ', ' , @{ $AoA[ 0 ] } ) , "\n";
__DATA__
1 2 3
4 5 6
7 8 9
A B C
D E F
G H I
J K L
M N O
P Q R
S T U
V W X
Y Z !
(stephen) Re: Short (and clever?) CSV-to-AoA
by stephen (Priest) on Apr 23, 2001 at 20:24 UTC
|
Interesting...
The code seems to run just fine without the "unless". Doing the 'push' on it creates the inner list. (Tested.)
I'm afraid I found your description a bit misleading, since you're not actually reading comma-separated values. :) Your values are separated by spaces. You output a comma-separated value list of the columns in the database (without escaping or quoting any commas that might be in the data).
stephen
| [reply] |
|
I would have to agree with this, and add that even if it was changed
to split ',', it still wouldn't work on fields that have embedded commas
(surrounded by double quotes).
-l
| [reply] |
|
Hmmm ... it runs fine as is for me with Activestate.
Sorry about the comma confusion, I was using 'CSV' in its
generic sense (like Text::CSV_XS which handles much more than
commas as field delimiters).
There won't be any commas in the data. It's quite clean.
I see I've (again) assumed that everyone could read my mind
and knew everything I know about the problem, sorry.
| [reply] |
|
| [reply] |
|
Re: Short (and clever?) CSV-to-AoA
by merlyn (Sage) on Apr 23, 2001 at 20:35 UTC
|
Is this really any better than:
my @AoA = map [split], <DATA>;
-- Randal L. Schwartz, Perl hacker | [reply] [d/l] |
|
Yes, it is much better ... Because my code does
something different than yours does. :)
My code turns each *column* of DATA into a
single anonymous array, stored in @AoA so the
print statement gives
1, 4, 7, A, D, G, J, M, P, S, V, Y
Your
my @AoA = map [split], <DATA>;
print join( ', ' , @{ $AoA[ 0 ] } ) , "\n";
gives 1, 2, 3. | [reply] [d/l] [select] |
|
Ahh, then it's just a matter of asking for the right print! The idiom for "extract a column while printing" is known, and reusable:
my @AoA = map [split], <DATA>;
print join(", ", map $AoA[0][$_], 0..$#{$AoA[0]}), "\n";
-- Randal L. Schwartz, Perl hacker | [reply] [d/l] |
|
|
|
Re: Short (and clever?) CSV-to-AoA
by jeroenes (Priest) on Apr 23, 2001 at 20:40 UTC
|
my @AoA = map{ [split] } <DATA>;
print join "\n", map{ join ',' @$_ } @AoA;
You could also turn to Supersplit code.
Have fun, Jeroen
"We are not alone"(FZ) | [reply] [d/l] |
|
1. You assign to an array in a for loop. That usually
is a sign for something inefficient.
It seemed more 'cool' to me than
inefficient. I particularly liked the fact that I could
get away with only one synthetic variable and that a loop
counter (of sorts). Why is it inefficient?
2. Your use of $#i will put all data in one array, so
you technically don't have an AoA, but just an array.
Errr ... but it *does* produce an AoA.
print join( ', ' , @AoA ) , "\n";
Gives
ARRAY(0x1b9528c), ARRAY(0x1b952a4), ARRAY(0x1b952d4)
3. You can loose the push/pop mechanism ...
See my comment to merlyn. | [reply] [d/l] [select] |
|
Mea culpa, I clearly missed the fact that you were transposing the table. But the other things stay.
1. Assigning in a for loop is something that goes automagically. If there is the need to assign to an array in something that already works on an array, that should ring a bell that something is inefficient there. Your for loop actually is an assignment and a conditional statement.That maybe nice for obfuscation (well, not really, but a bit maybe), but not cool IMHO.
3. As merlyn responded, you can rewrite that to a map, too.
Jeroen
"We are not alone"(FZ)
| [reply] |
(tye)Re: Short (and clever?) CSV-to-AoA
by tye (Sage) on Apr 24, 2001 at 01:04 UTC
|
Just to show another way (which I wouldn't actually suggest using due to the memory requirements, though it doesn't really use much more memory than some of other solutions suggested that turned out to be solutions for the wrong problem):
use mapcar;
my @AoA= mapcar{[@_]}map{[split]}<DATA>;
(requires mapcar -- map for more than one list)
-
tye
(but my friends call me "Tye") | [reply] [d/l] |
|
|