只有两个类接口可以被遍历:Iterator 和IteratorAggregate(任何其他都必须实现其中之一)。
迭代器
Iterator的第一个元素可以通过如下方式获取:
$iterator->rewind();
if (!$iterator->valid()) {
throw new Exception('There is no any element!');
}
$firstElement = $iterator->current();
如果你确定:
-
$iterator 从未被foreach 遍历过,或者如果是,但循环从未被break 或return 停止过(从 PHP 7 开始,这一点无关紧要,因为 foreach 不会影响指针)
- 从来没有叫过
$iterator->next();
您可以省略前面示例中的$iterator->rewind();。
如果您确定$iterator 中的元素计数不为零,您甚至可以省略条件块测试$iterator->valid()。
因此,如果保留这些先前的条件,那么您需要的只是:
$firstElement = $iterator->current();
迭代器聚合
IteratorAggergate 实际上只是一个 Iterator 或另一个 IteratorAggregate 的信封。从逻辑上讲,这意味着最后有一个迭代器。
如果您知道迭代器的深度,只需抓住它并像第一个示例一样使用:
$iterator = $iteratorAggregate->getIterator();
但如果您现在不了解深度,您可以使用同样适用于迭代器的解决方案:
$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);
不幸的是如果是 biig 数组,这有点矫枉过正,因为尽管我们只需要一个,但必须创建所有元素的副本。此外,如果迭代器是无限的Generator,您将耗尽内存。
有一个可行的解决方案:
while ($iterator instanceof \IteratorAggregate) {
$iterator = $iterator->getIterator();
}
// $iterator now contains instance of Iterator
我为一个包含 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();
LLAP