如何在PHP的foreach循环中重复特定的迭代?

时间:2018-03-05 05:12:26

标签: php foreach iteration

由于PHP中没有迭代器,循环数组而不获取数组长度的唯一方法是使用foreach循环。

假设我有以下循环:

foreach ($testing_array as $testing_entry) {
    $result = my_testing_api_call($testing_entry);
    if ($result == 'server dead')
        break;
    else if ($result == 'done') {
        // do something to handle success code
        continue;
    }
    else {
        sleep(5);
        // I want to retry my_testing_api_call with current $testing entry, but don't know what to write
    }
}

一种方法是使用for循环。

for ( $i=0; $i < count($testing_array); $i++ ) {
    $result = my_testing_api_call($testing_entry[$i]);
    if ($result == 'server dead')
        break;
    else if ($result == 'done') {
        // do something to handle success code
        continue;
    }
    else {
        sleep(5);
        $i--; //so it will repeat the current iteration.
    }
}

问题是$testing_array最初并没有使用数字作为索引,所以我必须做一些数据按摩来使用for循环。有没有办法在foreach循环中重复特定的迭代?

3 个答案:

答案 0 :(得分:7)

也许一段时间会对你有用。

未经测试的代码:

foreach ($testing_array as $testing_entry) {
    do {
        $result = my_testing_api_call($testing_entry);
        if ($result == 'server dead') {
            break 2;  // break both loops
        } elseif ($result == 'done') {
            // do something to handle success code
        } else {
            sleep(5);
            // I want to retry my_testing_api_call with current $testing entry, but don't know what to write
        }
    } while ($result !== 'done');
}

或单个循环结构,在迭代时销毁输入数组。

未经测试的代码:

$result = '';
while ($testing_array && $result !== 'server dead') {
    $result = my_testing_api_call(current($testing_array));
    if ($result == 'done') {
        // do something to handle success code
        array_shift($testing_array);
    } elseif ($result !== 'server dead') {
        sleep(5); // I want to retry my_testing_api_call with current $testing entry, but don't know what to write
    }
}

或者,如果您不需要for中的密钥,则可以使用$test_arrayarray_values()编入索引来使用// do something循环。

$testing_array = array_values($testing_array);
for ($i=0, $count=count($testing_array); $i < $count; ++$i) {
    $result = my_testing_api_call($testing_entry[$i]);
    if ($result == 'server dead') {
        break;
    } else if ($result == 'done') {
        // do something to handle success code
    } else {
        sleep(5);
        --$i; //so it will repeat the current iteration.
    }
}

如果您确实需要按键向下脚本,但是想要使用for,则可以存储一个索引数组的键,这样您就可以使用$i来访问密钥并保持数据同步性。

我的最终建议:

使用while (key($testing_array) !== null) {...}移动指针而不破坏元素。

代码:(Demo

$array1 = [
    "one" => 1,
    "two" => 2,
    "three" => 3,
    "four" => 4
];

while (key($array1)!==null) {  // check if the internal pointer points beyond the end of the elements list or the array is empty
    $current = current($array1);
    $key = key($array1);
    echo "$key => $current\n";         // display current key value pair
    if ($current < 3) {                // an arbitrary condition
        echo "\t";
        $array1[$key] = ++$current;    // increment the current value
    } else {                           // current value is satisfactory
        echo "\t(advance pointer)\n";
        next($array1);                 // move pointer
    }
}

输出:

one => 1
    one => 2
    one => 3
    (advance pointer)
two => 2
    two => 3
    (advance pointer)
three => 3
    (advance pointer)
four => 4
    (advance pointer)

答案 1 :(得分:0)

您正在尝试在循环中处理两个不同的事情,这使得编写干净的控制流很困难。您可以将重试逻辑与结果处理分开:

function call_api_with_retry($entry) {
  do {
    if (is_defined($result)) sleep(5);
    $result = my_testing_api_call($entry);
  } while ($result != 'done' && $result != 'server dead');
  return $result;
}

foreach ($testing_array as $testing_entry) {
    $result = call_api_with_retry($testing_entry);
    if ($result == 'server dead')
        break;
    else if ($result == 'done') {
        // do something to handle success code
        continue;
    }
}

(可能存在语法错误,自编写PHP代码以来已经有一段时间了)

答案 2 :(得分:0)

要重复单个特定迭代,您需要添加控制机制,毕竟这不是预期的行为。
这里有很多建议,但都有些过度设计。

PHP 是 C 的高级派生,两种语言都有“goto”运算符,它的名声很差,因为历史上人们使用它太多了。 最后,foreach/while 循环在内部只是一个“goto”操作。

代码如下:

foreach ($array as $key => $value)
{
restart:
if ($value === 12345) goto restart;
}

这就是应该这样做的方式,请记住,这可能会导致无限循环,就像示例中一样。

看下一个没有goto的复杂版本:

foreach ($array as $key => $value) while(1)
{
if ($value === 12345) continue;
break;
}

这和goto本质上是一样的,只是多了一些代码。 如果您想“中断”或“继续”foreach 循环,您可以编写“break 2”或“continue 2”