【问题标题】:PHP: how to move array pointer inside foreach loop?PHP:如何在 foreach 循环中移动数组指针?
【发布时间】:2012-05-05 04:27:46
【问题描述】:
$animals = array('cat', 'dog', 'horse', 'elephant');
foreach($animals as $animal)
{
   var_dump($animal);
   next($animals);
}

上面的代码输出:猫、狗、马、大象。我认为next 函数应该移动$animals 的内部指针,因此我应该得到这个输出:猫,马。

如何使 $animals 的内部指针向前(和向后)移动,使其在 foreach 中受到影响?

编辑 1:

来自手册:

As foreach 依赖于内部数组指针在 循环可能会导致意外行为。

不过,我认为这是我需要做的。

编辑 2:

根据“您的常识”的链接,我将对我的问题提供更详细的解释。这是一些伪代码:

array $foos;

start loop of $foos
 - do thing #1
 - do thing #2
 - do thing #3
 - keep doing thing #3 while the current value of $foos in the loop meets a certain criteria
loop

当执行返回到循环的开始时,它应该从#3 访问的最后一个数组继续。 请注意,数组是关联的,因此 for ($i = 0 ... 方法不起作用。

【问题讨论】:

  • 这不是对现实生活任务的解释,而是同一个 xy 问题。为什么需要它?
  • 在这个实现细节问题中可能隐藏了一个更简洁的设计

标签: php


【解决方案1】:

您可以创建一个ArrayIterator­Docs,即seekable­Docs

因为它是一个迭代器,你可以改变 位置 同时你迭代它,一些基本的例子:

foreach ($iterator as $current) {
    $iterator->next();
}

它应该提供开箱即用的一切。如果没有,您也可以自己封装您的需求到Iterator­Docs

【讨论】:

    【解决方案2】:

    您不应将foreach 与直接指针访问混用。如果您想在数组中移动,只需将foreach 替换为C 风格的for。它在顶部更冗长,但使用与 foreach 情况相同的循环体,不同之处在于您可以使用内部指针并获得所需的结果。

    $animals = array('cat', 'dog', 'horse', 'elephant');
    for ($animal = current($animals), $index = key($animals); 
           $animal; 
           $animal = next($animals), $index = key($animals)) {
      print "$index:";
      var_dump($animal);
      next($animals);
    } 
    

    输出:

    0:string(3) "cat"
    2:string(5) "horse"
    

    当您实际上在数组中来回移动时,使用像foreach 这样的直通迭代构造非常容易产生误导。上面的for 循环在这方面更好,但不是很多; while 循环,在循环体中明确说明了所有细节,可能是最佳选择。

    【讨论】:

    • 马克,我已经更新了原始问题,以便更好地解释我正在尝试做的事情。希望对您有所帮助。
    • 上述 for() 循环的行为与数组上的 foreach() 循环完全相同。如果您正在使用as $key => $value,那么您只需添加对key 的调用,我现在已经完成了。
    • 我对你的 for 循环中的第二个参数有点困惑。这甚至是有效的语法吗?
    • 它是有效的 - 代码按照编写的方式工作。你有什么问题?如果您愿意,我们可以聊天。
    【解决方案3】:

    Mark 的解决方案非常接近,但如果数组包含像 0、false 或 "" 这样在第二个 for 循环表达式中评估为 false 的值,则会失败。

    此解决方案适用于所有数组,并且更接近 for 循环的“精神”。第一个循环表达式中的 reset() 确保我们从数组的开头开始,这将是 foreach 的情况。 for 循环中的第二个表达式需要评估数组指针指向的元素是否存在。如果数组指针指向数组末尾之外或数组为空,则 key() 返回 null。第三个表达式在每次迭代结束时使数组指针前进。

    $animals = array('cat', 'dog', 'horse', 'elephant');
    for (reset($animals); key($animals) !== null; next($animals)) {
        $animal = current($animals);
        var_dump($animal);
        next($animals);
    }
    

    这个输出:

    string(3) "cat"
    string(5) "horse"
    

    【讨论】:

    • 它实际上看起来像一个for循环,可以在很多情况下使用,并且可以解决问题。谢谢。
    【解决方案4】:

    & 添加到值

    foreach ($variable as $key => &$value) {
    
    }
    

    现在$value 引用$variable[$key] 地址

    【讨论】:

    • 当您在执行 foreach 循环时想要更新数组的值时,这非常有用。另一种方法是在 for 循环中引用它,例如 $variable[$key] = 'MyNewValue';
    【解决方案5】:

    我认为因为他只想跳过元素,他可以在 foreach 中使用“继续”和 if 子句。

    $skip=array ('dog', 'elephant');
    $animals = array('cat', 'dog', 'horse', 'elephant');
    foreach($animals as $animal)
    {
       if (in_array($animal, $skip)) {
           continue;
       }
       var_dump($animal);
    }
    

    这将输出:

    string(3) "cat" 
    string(5) "horse"
    

    没有 continue 的变体 2 效果相同:

    $skip=array ('dog', 'elephant');
    $animals = array('cat', 'dog', 'horse', 'elephant');
    foreach($animals as $animal)
    {
       if (!in_array($animal, $skip)) {
            var_dump($animal);
       }
    
    }
    

    【讨论】:

      【解决方案6】:

      您不需要在 foreach 循环结束时手动增加指针 - 它会自动完成。您只需要:

      foreach($animals as $animal) {
          var_dump($animal)
      }
      

      【讨论】:

      • OP 正在尝试跳过元素,@andrewsi。
      • 我知道,但我真的想将指针前进到下一项。请参阅我在原始帖子中期望的示例输出。
      • 给自己的备忘录:stackoverflow 和失眠不要混在一起
      猜你喜欢
      • 2011-06-09
      • 2020-05-17
      • 1970-01-01
      • 2019-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-09
      • 1970-01-01
      相关资源
      最近更新 更多