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

Dear Monks,

I would like to avoid overwriting elements in my array. Could you give me some advice ? The value are overwritten because I sort the data into several categories and some elements belong to the same catogory. Thanks

Here is my code (checked)

#! usr/bin/perl -w use strict; use File::Copy; my $summary_excel_file = "all_weeks_classified_per_hour.csv"; open my $OUTFILE, q{>}, $summary_excel_file; print $OUTFILE "hour_position;before H-24;"; my @list = (1..24); @list = reverse @list; my $i; foreach $i(@list){ my $j = $i - 1; print $OUTFILE "between H-$i and H-$j;"; } @list = (1..24); foreach $i(@list){ my $j = $i - 1; print $OUTFILE "between H+$j and H+$i;"; } print $OUTFILE "\n"; print $OUTFILE "legend;"; my @Elements; my @TXT = glob("*.txt"); print STDOUT "@TXT\n"; foreach my $txt (@TXT){ open my $TXT, q{<}, $txt or die; while(<$TXT>){ my ($reg, $value, $anticipation) = (split /;/)[0,1,5]; my $relative_position = -$anticipation; if ($relative_position <= -1440){ $Elements[0] = $value; } foreach my $k (-24..23){ ### ] inf_limit ____________ pos in time ______________ +sup_limit____________> time my $inf_limit = 60*$k; my $sup_limit = 60*($k+1); my $l= $k + 25; if (($relative_position > $inf_limit) && ($relative_positi +on <= $sup_limit)){ $Elements[$l] = $anticipation; } } if ($relative_position > 1440 ){ $Elements[49] = $value; } } } my $nb = @Elements; foreach my $i(0..$nb){ if (defined $Elements[$i]){ $Elements[$i] =~ s/\s+//; print $OUTFILE "$Elements[$i];"; } else{ print $OUTFILE ";"; } } close $OUTFILE;
and here are the "*.txt" files
EGLLA22;0.1;380;01;22/10/2006;100
EGLLA22;0.1;380;01;22/10/2006;90
EGLLA22;0.1;380;01;22/10/2006;110

Replies are listed 'Best First'.
Re: adding elements to already exisiting elements in an array
by samtregar (Abbot) on May 14, 2008 at 16:31 UTC
    Instead of storing your data in a flat array, store it in an array of arrays. To do that, replace your assignments with code like:

       push @{$Elements[$l]}, $anticipation;

    That puts a reference to an anonymous array in $Elements[$l] which you add values to using push(). Then later you can access the values an index like:

       my @values = @{$Elements[$l]};

    -sam

Re: adding elements to already exisiting elements in an array
by Erez (Priest) on May 14, 2008 at 16:52 UTC

    Without going in depth to your code, I can think of two ways of doing that:

    push @list, $element unless grep {$_ eq $element} @list; #or keys %hash = @list; $hash{$element}++ unless exists $hash{$element};

    Stop saying 'script'. Stop saying 'line-noise'.
    We have nothing to lose but our metaphors.

      Did you mean @hash{@list} = ();?

      keys %hash = @list is legal, but all it does is preallocate storage, it does not actually create any keys for %hash.

      use strict; use warnings; my @list = qw(A B C); my %hash; keys %hash = @list; for my $element ( qw(D A) ) { $hash{$element}++ unless exists $hash{$element}; } my @new_list = keys %hash; print "Keys are @new_list.\n"; # now insert @list @hash{@list} = (); @new_list = keys %hash; print "Keys are @new_list.\n";
Re: adding elements to already exisiting elements in an array
by regexes (Hermit) on May 15, 2008 at 07:14 UTC
    Hello,

    In addition to samtregar's comments below, if you know that you will have multiple entries, then you need to initialize the array as an array reference to begin with... for example,


    Note: code has not been tested.

    if ( ref( $Elements[$1] ) eq "ARRAY" ) { push ( @{$Elements[$l]} }, $value ); } else { $Elements[$1] = [$value]; }
    See perldoc -f ref for some details...

    Hope this helps!

    regexes


    -------------------------
    Nothing in the world can take the place of persistence. Talent will not; nothing is more common than unsuccessful men with talent. Genius will not; unrewarded genius is almost a proverb. Education will not; the world is full of educated derelicts. Persistence and determination are omnipotent. The slogan "press on" has solved and always will solve the problems of the human race.
    -- Calvin Coolidge, 30th President of the USA.
      if ( ref( $Elements[$1] ) eq "ARRAY" ) { push ( @{$Elements[$l]} }, $value ); } else { $Elements[$1] = [$value]; }

      Note that you do not need to test whether you already have an array ref. as Perl will auto-vivify an anonymous array for you.

      $ perl -MData::Dumper -e' > @arr = (1, 2); > push @{ $arr[2] }, 3, 4; > push @arr, 5; > print Data::Dumper->Dump([\ @arr], [q{*arr}]);' @arr = ( 1, 2, [ 3, 4 ], 5 ); $

      Note also that samtregar's comments are above yours, you may have your monitor upside down :-)

      Cheers,

      JohnGG