PHP的Iterator方法如何有效(),current()和next()表现如何?

前端之家收集整理的这篇文章主要介绍了PHP的Iterator方法如何有效(),current()和next()表现如何?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我从 MAMP开始使用PHP 5.3.6.

我有一个用例,最好使用PHP的Iterator接口方法,next(),current()和valid()来迭代集合.在我的特定情况下,foreach循环对我不起作用.简化的while循环可能看起来像

<?PHP
while ($iter->valid()) {
  // do something with $iter->current()
  $iter->next();
}

当$iter实现PHP的Iterator接口时,上述代码是否始终有效? PHP的foreach关键字如何处理迭代器?

我问的原因是我写的代码可能会被赋予ArrayIterator或MongoCursor.两者都实现了PHP的Iterator接口,但它们的行为方式不同.我想知道PHPPHP的Mongo扩展中是否存在错误.

ArrayIterator :: valid()在任何对next()的调用之前返回true – 在创建ArrayIterator之后立即返回true.

MongoCursor :: valid()仅在第一次调用next()后返回true.因此,上面的while循环永远不会执行.

有可能是冗长的,下面的代码演示了这些断言:

<?PHP

// Set up array iterator
$arr = array("first");
$iter = new \ArrayIterator($arr);

// Test array iterator
echo(($iter->valid() ? "true" : "false")."\n"); // Echoes true
var_dump($iter->current()."\n");                // "first"
$iter->next();
echo(($iter->valid() ? "true" : "false")."\n"); // Echoes false


// Set up mongo iterator
$m = new \Mongo();
$collection = $m->selectDB("iterTest")->selectCollection("mystuff");
$collection->drop(); // Ensure collection is empty
$collection->insert(array('a' => 'b'));
$miter = $collection->find(); // should find one object

// Test mongo iterator
echo(($miter->valid() ? "true" : "false")."\n"); // Echoes false

$miter->next();

echo(($miter->valid() ? "true" : "false")."\n"); // Echoes true
var_dump($miter->current());                     // Array(...)

哪种实现是正确的?我发现很少有文档可以支持这两种行为,官方的PHP文档要么模糊不清,要么我读错了. doc for Iterator :: valid()表示:

This method is called after Iterator::rewind() and Iterator::next() to check if the current position is valid.

这表明我的while循环应首先调用next().

然而PHP documentation for Iterator :: next说:

This method is called after each foreach loop.

这表明我的while循环是正确的.

总结一下 – PHP迭代器应该如何表现?

这是个有趣的问题.我不确定为什么foreach不适合你,但我有一些想法.

看看the Iterator interface reference page上给出的示例.它显示PHP的内部实现foreach调用Iterator方法的顺序.特别要注意的是,首次设置foreach时,第一个调用是rewind().这个例子虽然没有很好地注释,但却是我答案的基础.

我不确定为什么MongoCursor在调用next()之前不会为valid()返回true,但是你应该能够通过在循环之前调用rewind()来重置任何类型的对象.所以你会:

// $iter may be either MongoCursor or ArrayIterator

$iter->rewind();
while( $iter->valid() ){
    // do something with $iter->current()
    $iter->next();
}

我相信这对你有用.如果没有,Mongo类可能会有错误.

编辑:Mike Purcell的答案正确地指出ArrayIterator和Iterator是不一样的.但是,ArrayIterator实现了Iterator,因此您应该能够使用rewind(),就像我在其中任何一个上面所示.

原文链接:https://www.f2er.com/php/138092.html

猜你在找的PHP相关文章