http://www.perlmonks.org?node_id=996678

zing has asked for the wisdom of the Perl Monks concerning the following question:

Hi all , I have this data file

b c a

a c d

d e b

And this code reads this data file into a 2d array.
use strict; use warnings; use Data::Dumper; # use PDL; my @S; while (<>) { push @S, [ split ]; } print "-----TRIPLETS-------\n"; print Dumper \@S; print "\n$S[0][1]\n"; # Find the number of vertices my @L; for my $i ( 0 .. $#S ) { for my $j ( 0 .. $#{ $S[$i] } ) { #print "elt $i $j is $S[$i][$j]\n"; push (@L,$S[$i][$j]); } }
Now what I want is another array which reads only first two columns of the array @S.

b c

a c

d e

Replies are listed 'Best First'.
Re: How to save first two columns of an array into another array
by toolic (Bishop) on Oct 01, 2012 at 15:41 UTC
    Grab a slice of each array in @S:
    use strict; use warnings; use Data::Dumper; my @S; while (<DATA>) { push @S, [split]; } print "-----TRIPLETS-------\n"; print Dumper \@S; my @new = map { [@{ $_ }[0 .. 1]] } @S; print Dumper \@new; __DATA__ b c a a c d d e b

    Output:

    -----TRIPLETS------- $VAR1 = [ [ 'b', 'c', 'a' ], [ 'a', 'c', 'd' ], [ 'd', 'e', 'b' ] ]; $VAR1 = [ [ 'b', 'c' ], [ 'a', 'c' ], [ 'd', 'e' ] ];
      Ok and how do I read the same (i.e. those first two columns into a hash). this is what I tried.
      my %h; my @a = map { [@{ $_ }[0]] } @S; my @b = map { [@{ $_ }[1]] } @S; @h{@a} = @b; print Dumper(@a); print Dumper(@b); print Dumper(%h); print "or\n"; print Dumper(\%h);
      But the output is wrong
      $VAR1 = { 'ARRAY(0x8411210)' => [ 'e' ], 'ARRAY(0x840d768)' => [ 'c' ], 'ARRAY(0x83f3308)' => [ 'c' ] };

        Is this what you wanted?

        my %h = map { $_->[0] => $_->[1] } @S; print Dumper(\%h);

        Output:

        $VAR1 = { 'a' => 'c', 'b' => 'c', 'd' => 'e' };

        Note: Once you put the data into a hash, the original order of the keys is lost. This is the way hashes work.

        Hope that helps,

        Athanasius <°(((><contra mundum

        In your code above, you are creating @a & @b as arrays of references to (one element) arrays. Perhaps what you intend is something like:
        my @a = map { ${ $_ }[0] ] @S;
        TJD
      Hi guys, there's one more thing Im stuck with. Suppose I have these points=(a,b,c,d);

      Then I want to find the set of triplets induced by these 4 vertices.

      For example for above four points the induced triplets should be:
      b c a a c d
      Whereas for vertices=(d,e,a) there isn't any triplet in the data.
Re: How to save first two columns of an array into another array
by Athanasius (Archbishop) on Oct 01, 2012 at 16:44 UTC

    On a side note, I just want to point out that the code:

    # Find the number of vertices my @L; for my $i (0 .. $#S) { for my $j (0 .. $#{$S[$i]}) { push(@L, $S[$i][$j]); } }

    can be simplified down to:

    my @L = map { @$_ } @S;

    since it’s just flattening a 2-dimensional list into a 1-dimensional list.

    I know only too well how hard it is to switch from thinking in C to thinking in Perl. But persevere, it’s worth the effort!

    Hope that helps,

    Athanasius <°(((><contra mundum

      Or to explore the language just a little more:

      my @l; push @l, @$_ for @S;

      to show statement modifiers and that push can push multiple elements at a time.

      Update: Fix array name inconsistency.

      True laziness is hard work
Re: How to save first two columns of an array into another array
by vagabonding electron (Curate) on Oct 03, 2012 at 11:06 UTC
    Since your data file seems to be a text file (like a csv only with whitespace as separator) you could consider using Text::CSV_XS:
    #!/usr/bin/perl use strict; use warnings; use Text::CSV_XS; use Data::Dumper; my $param = { binary => 1, auto_diag => 1, sep_char => ' ', eol => $/, }; my %hash; my $csv = Text::CSV_XS->new ( $param ); while ( my $row = $csv->getline( *DATA ) ) { print "@$row[0,1]\n"; # or whatever. $hash{$row->[0]} = $row->[1]; # read into a hash. } print Dumper \%hash; __END__ b c a a c d d e b
    Output of a Data::Dumper print statement is:
    $VAR1 = { 'a' => 'c', 'b' => 'c', 'd' => 'e' };

    Update: Typo corrected.