0

I want to make a loop where I go through all the elements in one array (@array1), and if the same element is found in another array (@array2), I want the value from a third array (@array3) with the same index to be added to the first array and deleted from the third array. I tried it this way, however the line with the if-statement runs on unitialized values, and it loops forever.

    foreach my $elem1 (@array1){
        my $i = 0;
        while ($i < scalar @array2){
            if($array2[$i]==$elem1){
                push (@array1, $array3[$i]);
                delete $array2[$i];
            }
            else{
                $i++;
            }
        }
    }
user2335015
  • 111
  • 11
  • 3
    The `delete` function is intended for use mainly with hashes, not arrays. You want `splice`. See http://perldoc.perl.org/functions/delete.html. More generally, there's a better way to solve this problem. – FMc May 09 '13 at 13:53
  • 1
    Your comments below suggest that you have mistakenly described the algorithm you desire. Please show us a clear example of what you want — show us what the arrays might look like before and after you perform your desired operation. – pilcrow May 09 '13 at 14:44

3 Answers3

1

The problem is you do not increment $i if the element matches. Delete the else.

choroba
  • 231,213
  • 25
  • 204
  • 289
  • But if I delete the first element array2, then there must be a new first element, so $i should only be incremented if I dont delete an element right? – user2335015 May 09 '13 at 13:53
1

Well, here's one way to deal with the problem (to the extent that I understand what you want to do). Whenever you need to answer questions about membership, you probably want to use a hash.

use strict;
use warnings;

my @array1 = ( 11, 22, 33,  44);
my @array2 = ( 11,  2,  3,  44,  5,   44);
my @array3 = (-11, -2, -3, -44, -5, -444);

# Keep track of every value in @array1.
my %vals = map { $_ => 1 } @array1;

my @keep_indexes;

# Go through @array2, either adding the corresponding
# value in @array3 to @array1 or storing the array index.
for my $i (0 .. $#array2) {
    if ($vals{$array2[$i]}){
        push @array1, $array3[$i];
    }
    else {
        push @keep_indexes, $i;
    }
}

# Rebuild @array3 from the indexes that we stored.
# Change this to @array2 if you want to delete from that array instead.
@array3 = map $array3[$_], @keep_indexes;

print join(' ', @array1), "\n"; # 11 22 33 44 -11 -44 -444
print join(' ', @array2), "\n"; # 11 2 3 44 5 44
print join(' ', @array3), "\n"; # -2 -3 -5

I dislike that code, so here are a few caveats:

  • Any time you have numbered variable names (@array1, @array2, etc.), you're headed for confusion. You need better variable names or, more likely, a better data structure.
  • Any time you find yourself in the business of maintaining parallel arrays, you should consider whether a better data structure would help.
FMc
  • 41,963
  • 13
  • 79
  • 132
0

You are deleting an element from array2, not array3 as stated in the question. I think the delete operation sets the array element to undef. The next time around the loop it checks that same element that is now undef against $elem. Hence the error. Then it does he same again and again.

AdrianHHH
  • 13,492
  • 16
  • 50
  • 87
  • Rather than `delete` the array element, use `splice`. See http://stackoverflow.com/questions/174292/what-is-the-best-way-to-delete-a-value-from-an-array-in-perl . The original question wants the element in array 3 with the same index as the array2 element, but as elements are being removed from array2 the indexes will become misaligned. Is that desired? – AdrianHHH May 09 '13 at 15:04