Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Short (and clever?) CSV-to-AoA

by scott (Chaplain)
on Apr 23, 2001 at 19:55 UTC ( [id://74737]=perlmeditation: print w/replies, xml ) Need Help??

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 !

Replies are listed 'Best First'.
(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

      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

      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.

        Yes, it runs fine with the unless() statement. What I was saying was that it also runs fine without the unless() statement. :)

        You might also want to take a look at Data::Table on CPAN.

        stephen

Re: Short (and clever?) CSV-to-AoA
by merlyn (Sage) on Apr 23, 2001 at 20:35 UTC

      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.

        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

Re: Short (and clever?) CSV-to-AoA
by jeroenes (Priest) on Apr 23, 2001 at 20:40 UTC
    Well, there are some things that might be useful:
    1. You assign to an array in a for loop. That usually is a sign for something 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.
    3. You can loose the push/pop mechanism, replace that with a map.

    This is how I would write that:

    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)

      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.

        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)

(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")

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://74737]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (5)
As of 2024-03-28 08:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found