如何访问迭代器中的第一个元素?

neu*_*ert 16 php iterator

我正在使用一个PHP框架,它将SQL结果作为可迭代对象返回.问题是我有一个返回一行的SQL查询,我不想创建一个foreach-loop来获取第一个 - 也是唯一 - 元素.

那我该怎么做?

这些不起作用:

$obj->item(0)->propName;
$obj->next()->propName;
$obj[0]->propName;
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

Age*_*rum 21

假设"iterable",你的意思是对象实现了Iterator接口,你可以$obj->current()用来检索当前元素,所以$obj->current()->propName可能你想要的.

如果已经移动了迭代器指针(例如,如果它在a中使用foreach,它没有重置指针),则可以在调用$obj->rewind()之前调用将指针设置回第一个元素$obj->current().


hej*_*dav 10

只有两个可以遍历的类接口:IteratorIteratorAggregate(任何其他必须实现其中一个).


迭代器

迭代器的第一个元素可以如下获得:

$iterator->rewind();
if (!$iterator->valid()) {
    throw new Exception('There is no any element!');
}
$firstElement = $iterator->current();
Run Code Online (Sandbox Code Playgroud)

如果您确定:

  • $iterator从未被穿过foreach,或者如果它是,但环从未停止用breakreturn(因为PHP 7这一点是无关紧要的,因为的foreach不影响指针)
  • 从来没有打过电话 $iterator->next();

您可以省略$iterator->rewind();上一个示例中的内容.

如果您确定元素的$iterator数量为零,您甚至可以省略条件块测试$iterator->valid().

因此,如果保留这些先前的条件,那么您需要的只是:

$firstElement = $iterator->current();
Run Code Online (Sandbox Code Playgroud)

IteratorAggregate

IteratorAggergate实际上只是Iterator或其他IteratorAggregate的信封.从逻辑上讲,这意味着最后有一个迭代器.

如果您知道Iterator的深度级别,只需抓住它并使用第一个示例:

$iterator = $iteratorAggregate->getIterator();
Run Code Online (Sandbox Code Playgroud)

但是如果你现在没有深度,你可以使用一个也适用于Iterator的解决方案:

$array = iterator_to_array($iteratorAggregate);
// $array is an ordinary array now
if (count($array) === 0) {
    throw new Exception('There is no any element!');
}
$firstElement = reset($array);
Run Code Online (Sandbox Code Playgroud)

不幸的是,在biig数组的情况下,这有点过分,因为必须创建所有元素的副本,尽管我们只需要一个.此外,如果迭代器是一个无限的发生器,你将耗尽内存.

有一个解决方案有效:

while ($iterator instanceof \IteratorAggregate) {
    $iterator = $iterator->getIterator();
}
// $iterator now contains instance of Iterator
Run Code Online (Sandbox Code Playgroud)

我为10000个成员的数组做了一个简单的基准测试,这个解决方案快了近6倍.

因此,适用于所有情况的通用解决方案是:

while ($iterator instanceof \IteratorAggregate) {
    $iterator = $iterator->getIterator();
}
$iterator->rewind();
if (!$iterator->valid()) {
    throw new Exception('There is no any element!');
}
$firstElement = $iterator->current();
Run Code Online (Sandbox Code Playgroud)

LLAP