【问题标题】:reset a pointer for a for-loop in php在php中重置for循环的指针
【发布时间】:2015-06-19 01:07:51
【问题描述】:

给定以下代码

<?php
$a = array(1,2,3,4,5,6);
$c=0;
foreach($a as $v){
    if($v==5&&$c==0){
        $c=1;
        reset($a);
    }
    var_dump($v);
}

如何重置指针,使其打印 1,2,3,4,5,1,2,3,4,5,6?

我知道在这种情况下我可以简单地

<?php
$a = array(1,2,3,4,5,6);
$c=0;
for($i=0;$i<count($a);++$i){
    $v = $a[$i];
    if($v==5&&$c==0){
        $c=1;
        $i=-1;  //because of the loop ++$i
    }
    var_dump($v);
}

但是我有一段复杂得多的代码,解决方案并不像重写循环那么简单(不是数字键)。

有任何 PHP 大师可以在这里帮助我吗?

【问题讨论】:

  • 您的第一个示例应该可以工作。 reset() (php.net/manual/en/function.reset.php) 是该案例的功能。
  • 应该,但没有!!
  • 仅供参考,“foreach”实际上如何“工作”很“有趣,也许:How 'foreach' actually works。我可以建议您不要在“foreach 循环”中调整“内部指针”吗?当“内部指针”被重置时,还有其他“循环”结构可以正常工作。
  • 如果我可以让它在不重置的情况下工作,我会的。我去看看链接,谢谢

标签: php for-loop


【解决方案1】:

据记载:

注意:当 foreach 第一次开始执行时,内部数组指针会自动重置为数组的第一个元素。这意味着您不需要在 foreach 循环之前调用 reset()。

由于 foreach 依赖于内部数组指针,在循环内更改它可能会导致意外行为

http://php.net/manual/en/control-structures.foreach.php

不确定什么是“意外行为”,因为我从未尝试过...但手动使用 each() 可能更安全...在您的代码中也更清晰。

reset($a);
while(list($key, $val) = each($a)) {
    if($val==5&&$c==0){
        $c=1;
        reset($a);
    }
    var_dump($val);
}

解释 Foreach 问题

我以为我之前看到过,你不能依赖 foreach 中的内部指针……但这次在文档中找不到它……只有“意外结果”。不过,感谢一位评论者,我找到了以前在 foreach 中的文字:

除非数组被引用,否则 foreach 操作的是指定数组的副本,而不是数组本身。 foreach 对数组指针有一些副作用。不要在 foreach 期间或之后依赖数组指针而不重置它。”

http://php.net/manual/en/control-structures.foreach.php#114759

【讨论】:

  • while()each() 确实是这里最好的解决方案。
  • 我实际上打算将它添加到代码中,这是一个可行的解决方案,但因为 foreach 依赖于内部数组指针,我认为 reset 应该可以工作。谢谢
  • @Fabrizio,是的...这实际上让我有点困惑...我以为它说它在其他地方使用了不同的指针...根据该文档,我同意它似乎reset() “应该”工作。所以,我主要是在 cmets 中脱离“意外行为”方面。
  • @Fabrizio,好的,用可能的解决方案更新了我的答案以尝试...尝试在 foreach 中引用您的数组。
  • Parse error: syntax error, unexpected '&amp;' in [...][...] on line 3 -->此错误发生在您的第二个示例中。
【解决方案2】:

如果你是 OOP 的爱好者,你可以使用 ArrayIterator 类。

它的方法rewind()reset() function相同。

$a=array(1,2,3,4,5,6);//or $a=range(1,6);

$i=new ArrayIterator($a);

$c=0;

foreach($i as $k=>$v)
{
    if($v==5&&$c==0)
    {
        $c=1;
        $i->rewind();
    }
    var_dump($v);
}

unset($i);//delete the iterator, to free memory

您可以在http://writecodeonline.com/php/http://sandbox.onlinephpfunctions.com/ 上在线测试

@KevinNelson 的回答是正确的方法,但对于未经训练的人来说并不明显。


这段代码有问题。
由于迭代,数字 1 不会第二次回显。

但我有 2 个弗兰肯解决方案

解决方案1:跳过一个可忽略的元素,使用方法next()

$a=array(0,1,2,3,4,5,6);//or $a=range(0,6);

$i=new ArrayIterator($a);

$c=0;

$i->next();//jumps over the 1st element

foreach($i as $k=>$v)
{
    if($v==5&&$c==0)
    {
        $c=1;
        $i->rewind();
    }
    var_dump($v);
}

unset($i);

解决方案 2: 创建一个具有 'falsy' 值的元素(0nullfalse''...)并在循环中忽略它

$a=array(0,1,2,3,4,5,6);//or $a=range(0,6);

$i=new ArrayIterator($a);

$c=0;

foreach($i as $k=>$v)
{
    if($v==5&&$c==0)
    {
        $c=1;
        $i->rewind();
    }
    if($v)var_dump($v);
}

unset($i);

【讨论】:

  • 奇怪的是第二次跳过第一个值:eval.in/312989
  • @jeroen 我已经用一些 * franken-code* 修复了它。
猜你喜欢
  • 2020-02-25
  • 1970-01-01
  • 2018-07-27
  • 1970-01-01
  • 1970-01-01
  • 2019-11-29
  • 1970-01-01
  • 2019-09-14
  • 2023-03-30
相关资源
最近更新 更多