in reply to adding an index column to a multi-array derived from a csv data file

It works for me.

my @arr = ([1,1], [2,2], [3,3]); # [[1, 1], [2, 2], [3, 3]] $_->[2] = $i++ for @arr; # [[1, 1, 0], [2, 2, 1], [3, 3, 2]]

Are you sure your @multi_array contains array refs? If so, is the last index 1, such that assigning to index 2 will add a new element? The data in your previous post has a length of 3 elements, so index 2 is already populated.

You could generalise to:

$_->[$#{$_}+1] = $i++ for @arr; # or push @{$_}, $i++ for @arr;

Replies are listed 'Best First'.
Re^2: adding an index column to a csv data file
by ng0177 (Acolyte) on Jun 02, 2019 at 12:55 UTC
    my $i=0; $_->[2] = $i++ for @multi_array;

    works for me too now after resetting $i which masked it.

    You are right, the present data set has two columns and the other one three. I should have mentioned that.

    Thanks for helping out. The generalisation is useful to have.

      You could generalize this a bit further and eliminate the  $i variable (one less thing to worry about):

      c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my @multi_array = ([ 99, 88 ], [ 77, 66 ], [ 55, 44 ], ); ;; push @{ $multi_array[$_] }, $_ for 0 .. $#multi_array; dd \@multi_array; " [[99, 88, 0], [77, 66, 1], [55, 44, 2]]
      but I'm not sure this is really an improvement WRT clarity and maintainability! unshift or splice could be used to stuff the new element at other offsets in the array. The "pure index" version is even more obscure:
      c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my @multi_array = ([ 99, 88 ], [ 77, 66 ], [ 55, 44 ], ); ;; $multi_array[$_][ @{$multi_array[$_]} ] = $_ for 0 .. $#multi_array; dd \@multi_array; " [[99, 88, 0], [77, 66, 1], [55, 44, 2]]


      Give a man a fish:  <%-{-{-{-<

        The $i less variant is good for learning.

Re^2: adding an index column to a csv data file
by ng0177 (Acolyte) on Jun 02, 2019 at 17:56 UTC

    I realized I forgot all about the <cr>. I solved it this way - just for the records.

    my $i = 0; (chomp $_->[1], $_->[2] = $i++) for @multi_array;

    However, printing looks slighty odd due to a missing blank.

    print join(",", @{$_}),"\n" for (@multi_array); 4.20064619e-03, 5.30384531e+04,91 4.24680719e-03, 5.28570000e+04,92 ...
    I wonder why.

      It is probably due to the split not cleaning up leading spaces, or possible sequential spaces. It is hard to say without seeing that part of the code and the data.

      Could you provide the code and some example data? Your other response indicates it is not the same as your previous post.

      In any case, it could be cleaned up using a map or another loop, possibly embedded in your other code (but that could become a bit too obfuscatory).

      @arr = map {s/^\s+//} @arr;
        I am not sure how to delete/correct my reply looking at the documentation. Would you mind to point me to the right document? Thanks!

        Here is the code. The data has an extra blank in. The comment line does not work on the @multi_array, I suspect. I cannot figure out, too, how to print the added index as integers i.e. how to apply map to a part of the array.

        #!/usr/bin/perl -w # read data my @multi_array; push @multi_array, [split(',', $_)] for <DATA>; #@multi_array = map {s/\s//} @multi_array; # add counter column my $i = 0; (chomp $_->[1],$_->[2] = sprintf ("%d",$i++)) for @multi_ar +ray; #or push @{ $multi_array[$_] }, $_ for 0 .. $#multi_array; # modify columns ($_->[0] *= 1.0, $_->[1] /= 1.0) for @multi_array; # screen output print join(",", map { sprintf "%e", $_ } @{$_}),"\n" for @multi_array; __DATA__ 0.00000000e+00, 2.41644835e+00 1.20048018e-04, 2.38938189e+00 2.40096037e-04, 2.36473989e+00
Re^2: adding an index column to a csv data file
by ng0177 (Acolyte) on Jun 04, 2019 at 19:27 UTC
    I suggest the below code as the consolidated answer to my question, if there are no objections. The handling of blanks is redundant but could be modified for other purposes.
    #!/usr/bin/perl -w my @AoA = (); # ArrayOfArrays # read data plus add index while (<DATA>){ s/\s*//g; my @tmp = split ',',$_; $tmp[0] *= 1.0; $tmp[1] /= 1.0; $tmp[2] = $.; push @AoA,\@tmp; } # or #push @AoA, [split(/,\s*/, $_)] for <DATA>; #push @{ $AoA[$_] }, $_ for 0 .. $#AoA; # modify columns foreach my $row (@AoA) { foreach my $item (@$row) { $item =~ s/^\s+//; } $row->[0] *= 1.0; $row->[1] /= 1.0; } # or #($_->[0] *= 1.0, $_->[1] /= 1.0) for @AoA; # screen output printf "%e,%e,%d\n",@$_ for @AoA; __DATA__ 0.00000000e+00, 2.41644835e+00 1.20048018e-04, 2.38938189e+00 2.40096037e-04, 2.36473989e+00

      No objections from me. There will always be ways of rewriting code, but expressiveness is one of the advantages of Perl.