5

Is it ok to loop array again in nested loop and also change the array?

I've an URL's array with entries(as array key) of either an URL or domain:example.com

In case of this entry : domain:example.com I want to remove all URLS containing example.com as domain:

foreach (array_keys($urls1) as $line) {
        if (preg_match('/domain:(.*)/i', $line, $matches)) {
            $domain = $matches[1];
            foreach (array_keys($urls1) as $line2) {
                if ($url_domains[$line2] == $domain) {
                    unset($urls1[$line2]);
                }
            }
        }
    }
AgA
  • 1,858
  • 6
  • 28
  • 62
  • It's certainly ok to loop over it. But I'm not sure wheter it's ok to modify it and how. – Pavel Šimerda Apr 06 '14 at 06:01
  • It might be better to do an [`array_walk`](http://php.net/array_walk) or [`array_map`](http://php.net/array_map). If it works fine with this code, I don't see any reason to change it. – Dave Chen Apr 06 '14 at 06:09
  • 1
    http://stackoverflow.com/questions/10057671/how-foreach-actually-works?rq=1 http://stackoverflow.com/questions/1685689/how-is-an-array-in-a-php-foreach-loop-read?rq=1 http://stackoverflow.com/questions/2008866/unsetting-array-values-in-a-foreach-loop?rq=1 – Andy Librian Apr 06 '14 at 06:16

2 Answers2

2

There is no problem looping over it a second time, however you will get yourself and your code into a big knot if you start removing items. My suggestion would be to save a copy and modify that.

This is not ideal, but I'm not sure what you wish to do.

//Make a copy of your array
$URLCopy  = $urls1;

foreach (array_keys($urls1) as $line) {
    if (preg_match('/domain:(.*)/i', $line, $matches)) {
        $domain = $matches[1];
        foreach (array_keys($urls1) as $line2) {
            if ($url_domains[$line2] == $domain) {
                unset($URLCopy[$line2]);
            }
        }
    }
 }
Toby Allen
  • 10,562
  • 10
  • 70
  • 120
0

I ran into a similar problem and making a copy of the array was the answer. This was my problem:

If a particular text string existed towards the beginning of the file and (an array of approximately 80 members) matched a string towards the end of the file, I had to remove three lines towards the end. The problem that happened when I didn't use a copy is that the index would reset from 30, back to 9, and this caused me some issues.

This is what worked for me.

$rowCopy = $row

foreach($row as $index => &$line) {

    ////previous code

    if ($line[0] === "NM1" && $line[1] === "77") {
        //read through the $row array and find the NM*85 string
        foreach ($rowCopy as $index2 => $lineT) {

            if ($s = strpos($lineT, "NM1*85") !== false) {
                $npiTest = explode("*", $lineT);
                if (strcmp(preg_replace("/[^0-9,.]/", "", $npiTest[9]), $line[9]) === 0) {
                    // $line = false;
                    $index--;
                    unset($row[$index + 1]);
                    $index++;
                    unset($row[$index + 1]);
                    $index++;
                    unset($row[$index + 1]);
                    $erased = $erased + 3;
                    $index++
                }
            }
        }

    }

}