27

PHP 中是否有 SPL 反向数组迭代器?如果没有,实现它的最佳方法是什么?

我可以简单地做

$array = array_reverse($array);
foreach($array as $currentElement) {}

或者

for($i = count($array) - 1; $i >= 0; $i--)
{

}

但是有没有更优雅的方式呢?

4

11 回答 11

66

这是一个不复制也不修改数组的解决方案:

for (end($array); key($array)!==null; prev($array)){
  $currentElement = current($array);
  // ...
}

如果您还想引用当前键:

for (end($array); ($currentKey=key($array))!==null; prev($array)){
  $currentElement = current($array);
  // ...
}

这总是有效的,因为 php 数组键永远不能为空,并且比这里给出的任何其他答案都快。

于 2014-09-10T15:52:06.180 回答
14
$item=end($array);
do {
...
} while ($item=prev($array));
于 2011-03-15T17:33:23.823 回答
12

没有ReverseArrayIterator办法做到这一点。你可以做

$reverted = new ArrayIterator(array_reverse($data));

或者把它变成你自己的自定义迭代器,例如

class ReverseArrayIterator extends ArrayIterator 
{
    public function __construct(array $array)
    {
        parent::__construct(array_reverse($array));
    }
}

不使用array_reverse但通过标准数组函数迭代数组的稍长的实现将是

class ReverseArrayIterator implements Iterator
{
    private $array;

    public function __construct(array $array)
    {
        $this->array = $array;
    }

    public function current()
    {
        return current($this->array);
    }

    public function next()
    {
        return prev($this->array);
    }

    public function key()
    {
        return key($this->array);
    }

    public function valid()
    {
        return key($this->array) !== null;
    }

    public function rewind()
    {
        end($this->array);
    }
}
于 2011-03-15T18:01:55.057 回答
11

基于linepogl的回答,我想出了这个功能:

/**
 * Iterate an array or other foreach-able without making a copy of it.
 *
 * @param array|\Traversable $iterable
 * @return Generator
 */
function iter_reverse($iterable) {
    for (end($iterable); ($key=key($iterable))!==null; prev($iterable)){
        yield $key => current($iterable);
    }
}

用法:

foreach(iter_reverse($my_array) as $key => $value) {
    // ... do things ...
}

这适用于数组和其他可迭代对象,而无需先复制它。

于 2016-04-13T17:32:04.960 回答
9

根据您要执行的操作,您可能需要查看 spl 数据结构类,例如 SplStack。SplStack 实现了 Iterator、ArrayAccess 和 Countable,因此它主要可以像数组一样使用,但默认情况下,它的迭代器按 FILO 顺序进行。前任:

$stack = new SplStack();
$stack[] = 'one';
$stack[] = 'two';
$stack[] = 'three';

foreach ($stack as $item)
{
    print "$item\n";
}

这将打印

three
two
one
于 2011-03-15T17:37:14.793 回答
6

请注意,如果要保留数组的键,则必须将true其作为第二个参数传递给array_reverse

$array = array_reverse($array, true);
foreach ($array as $currentElement) {
    // do something here
}
于 2012-10-10T18:09:42.577 回答
5
$array = array_reverse($array);
foreach($array as $key => $currentElement) {}

这是更好的使用方式。如果它们不是顺序的或整数的,它也会处理键。

于 2011-03-15T17:33:33.993 回答
5

基于linepogl的回答...您可以通过避免current()调用来提高效率

for ($value = end($array); ($key = key($array)) !== null; $value = prev($array)) {
     // ... do something with $key => $value
}
于 2018-01-23T17:20:07.280 回答
1
$array=array(
    0 => 0,
    '1' => 1,
    2 => null,
    3 => false
);

$value=end( $array );                      // ← value for first iteration
while(($key=key( $array )) !== null) {
  echo "key=$key, value=$value\n";

  $value=prev( $array );                   // ← value for next iteration
}
于 2014-10-04T18:58:19.757 回答
0

这可能是一种更高效的方式,因为它不构造新数组。它还可以很好地处理空数组。

$item = end($items);
while($item)
{
    ...do stuff...
    $item = prev($items);
}
于 2013-01-05T00:02:47.410 回答
-2

$array1= 数组(10,20,30,40,50);

        for($i = count($array1) - 1; $i >= 0; $i--)
        {
            $array2[]  = $array1[$i];

        }

        echo "<pre>";
            print_r($array2);
        echo "</pre>";
于 2015-07-09T07:15:57.600 回答