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接口,但它们的行为方式不同.我想知道PHP或PHP的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()表示:
这表明我的while循环应首先调用next(). 然而PHP documentation for Iterator :: next说:
这表明我的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(),就像我在其中任何一个上面所示. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |