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

时间:2022-07-16 21:59:06

I'm using a PHP framework that returns SQL results as iteratable objects. Problem is I have a SQL query that that returns one row and I don't want to have to create a foreach-loop to get at the first - and only - element.

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

So how do I do it?

那我该怎么做?

These don't work:

这些不起作用:

$obj->item(0)->propName;
$obj->next()->propName;
$obj[0]->propName;

Any ideas?

2 个解决方案

#1


19  

Assuming by "iterable", you mean that the object implements the Iterator interface, you can use $obj->current() to retrieve the current element, so $obj->current()->propName is probably what you want.

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

If the iterator pointer has been moved (for example, if it was used in a foreach, which doesn't reset the pointer), then you can call $obj->rewind() to set the pointer back to the first element before you call $obj->current().

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

#2


9  

There are only two class interfaces that can be traversed: Iterator and IteratorAggregate (any other must implement one of them).

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


Iterator

First element of Iterator can be obtained as follows:

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

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

If you are sure:

如果您确定:

  • the $iterator was never been traversed by foreach, or if it was but the loop was never stopped with break;
  • $ iterator从来没有被foreach遍历,或者如果它是,但循环从未停止过中断;

  • there was never called $iterator->next();
  • 从来没有调用$ iterator-> next();

you can omit the $iterator->rewind(); from the previous example.

你可以省略$ iterator-> rewind();从前面的例子。

If you are sure the count of elements in $iterator is not zero, you can even omit the condition block testing $iterator->valid().

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

So if these previous conditions are preserved then what you need is just:

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

$firstElement = $iterator->current();

IteratorAggregate

You can't obtain first element any simply. IteratorAggergate is actually just an envelope for an Iterator or another IteratorAggregate. Logically that means there is an Iterator at the end. Unfortunately you don't know how many levels deep.

你不能简单地获得第一个元素。 IteratorAggergate实际上只是Iterator或其他IteratorAggregate的信封。从逻辑上讲,这意味着最后有一个迭代器。不幸的是你不知道有多少级别。

The simplest way to achieve the first element is:

实现第一个元素的最简单方法是:

$array = iterator_to_array($iteratorAggregate);
if (count($array) === 0) {
    throw new Exception('There is no any element!');
}
$firstElement = reset($array);

(and surprisingly exactly same solution works also for an Iterator!)

(令人惊讶的是,完全相同的解决方案也适用于迭代器!)

We are transforming it to an ordinary array so next procedure is a usual way to fetch the first element from an array. Unfortunately in case of biig array this is a little overkill because copy of all elements must be created despite we need just one.

我们正在将它转换为普通数组,因此下一个过程是从数组中获取第一个元素的常用方法。不幸的是,在biig数组的情况下,这有点过分,因为必须创建所有元素的副本,尽管我们只需要一个。

There is one solution that seems lax:

有一个解决方案似乎松懈:

while ($iteratorAggregate instanceof \IteratorAggregate) {
    $iteratorAggregate = $iteratorAggregate->getIterator();
}
$iterator = $iteratorAggregate;

and in next step we work with it like it was an Iterator in the very first example. I made a simple benchmark for an array of 10000 members and this solution was almost 6 times faster.

在下一步中,我们使用它,就像在第一个例子中它是一个迭代器一样。我为10000个成员的数组做了一个简单的基准测试,这个解决方案快了近6倍。

LLAP

#1


19  

Assuming by "iterable", you mean that the object implements the Iterator interface, you can use $obj->current() to retrieve the current element, so $obj->current()->propName is probably what you want.

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

If the iterator pointer has been moved (for example, if it was used in a foreach, which doesn't reset the pointer), then you can call $obj->rewind() to set the pointer back to the first element before you call $obj->current().

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

#2


9  

There are only two class interfaces that can be traversed: Iterator and IteratorAggregate (any other must implement one of them).

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


Iterator

First element of Iterator can be obtained as follows:

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

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

If you are sure:

如果您确定:

  • the $iterator was never been traversed by foreach, or if it was but the loop was never stopped with break;
  • $ iterator从来没有被foreach遍历,或者如果它是,但循环从未停止过中断;

  • there was never called $iterator->next();
  • 从来没有调用$ iterator-> next();

you can omit the $iterator->rewind(); from the previous example.

你可以省略$ iterator-> rewind();从前面的例子。

If you are sure the count of elements in $iterator is not zero, you can even omit the condition block testing $iterator->valid().

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

So if these previous conditions are preserved then what you need is just:

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

$firstElement = $iterator->current();

IteratorAggregate

You can't obtain first element any simply. IteratorAggergate is actually just an envelope for an Iterator or another IteratorAggregate. Logically that means there is an Iterator at the end. Unfortunately you don't know how many levels deep.

你不能简单地获得第一个元素。 IteratorAggergate实际上只是Iterator或其他IteratorAggregate的信封。从逻辑上讲,这意味着最后有一个迭代器。不幸的是你不知道有多少级别。

The simplest way to achieve the first element is:

实现第一个元素的最简单方法是:

$array = iterator_to_array($iteratorAggregate);
if (count($array) === 0) {
    throw new Exception('There is no any element!');
}
$firstElement = reset($array);

(and surprisingly exactly same solution works also for an Iterator!)

(令人惊讶的是,完全相同的解决方案也适用于迭代器!)

We are transforming it to an ordinary array so next procedure is a usual way to fetch the first element from an array. Unfortunately in case of biig array this is a little overkill because copy of all elements must be created despite we need just one.

我们正在将它转换为普通数组,因此下一个过程是从数组中获取第一个元素的常用方法。不幸的是,在biig数组的情况下,这有点过分,因为必须创建所有元素的副本,尽管我们只需要一个。

There is one solution that seems lax:

有一个解决方案似乎松懈:

while ($iteratorAggregate instanceof \IteratorAggregate) {
    $iteratorAggregate = $iteratorAggregate->getIterator();
}
$iterator = $iteratorAggregate;

and in next step we work with it like it was an Iterator in the very first example. I made a simple benchmark for an array of 10000 members and this solution was almost 6 times faster.

在下一步中,我们使用它,就像在第一个例子中它是一个迭代器一样。我为10000个成员的数组做了一个简单的基准测试,这个解决方案快了近6倍。

LLAP