SPL InfiniteIterator无法使用next或prev

问题描述 投票:1回答:3

我希望无限地像一个圆形数组。

我使用InfiniteIterator1进行以下设置,它无限地迭代$players。但实际上,我想知道下一个玩家以及此循环中的前一个玩家,如下所示

$players = new InfiniteIterator(new ArrayIterator(['Shobi', 'Jomit']));

foreach ($players as $player) {
    echo $player; // current player name comes properly infinetly
    echo next($players); // next player should come
    echo current($players); // current player should come
    echo prev($players); //previous player should come
}

next()prev()总是返回null

从文档中,我可以看到这些方法返回无效,但是有什么方法可以扩展InfiniteIterator并实现所需的这种机制吗?

如何使next()prev()与InfiniteIterator一起使用?

编辑current()返回当前项目,(意思是,它在逻辑中正常工作)

php iterator infinite-loop php-7.2 spl
3个回答
1
投票

如果不是使用迭代器,你可以使用一个数组和一个指向'current'条目的指针然后使用while(true)循环,它将继续运行(你总是可以添加一个break来阻止它进行测试或某些条件)。逻辑的各个部分检查当前玩家是否是最后一个 - 所以下一个是开始 - 或者如果它是第一个项目,那么前一个是最终项目。一旦它到达终点并且重新开始,增量也会重置......

$players = ['Shobi', 'Jomit'];
$playerKey = 0;
$playerCount = count($players);
while(true) {
    echo $players[($playerKey+1)%$playerCount].PHP_EOL; // next player
    echo $players[$playerKey].PHP_EOL; // current player
    echo $players[($playerKey>0)?$playerKey-1:$playerCount-1].PHP_EOL; //previous player
    $playerKey = ( $playerKey+1 == $playerCount )?0:$playerKey+1;
}

1
投票

您可以使用PHP迭代器,并执行以下操作:

$array = ['Shobi', 'Jomit', 'John', 'Jane', 'Smith'];

// Use NoRewindIterator to prevent MultipleIterator rewinding.
$players1 = new NoRewindIterator(new InfiniteIterator(new ArrayIterator($array)));
// Go to the end of array, i.e. set prev player.
for ($i = 0, $size = count($array); $i < $size - 1; $i++) {
    $players1->next();
}

$players2 = new InfiniteIterator(new ArrayIterator($array));
$players2->next();

// Use NoRewindIterator to prevent MultipleIterator rewinding.
$players3 = new NoRewindIterator(new InfiniteIterator(new ArrayIterator($array)));
$players3->next(); // Go to the second player, i.e. next player

// MultipleIterator will traverse three iterators at once.
// Since the pointer in each iterator differs in one position, we will have prev, curr and next.
$players = new MultipleIterator(MultipleIterator::MIT_NEED_ALL|MultipleIterator::MIT_KEYS_ASSOC);
$players->attachIterator($players1, 'prev');
$players->attachIterator($players2, 'curr');
$players->attachIterator($players3, 'next');

$i = 0;
foreach ($players as $player) {
    print_r($player);

    if (++$i >= 10) {
        break;
    }
}

请看the demo


0
投票

发布我最终提出的答案。

无限迭代器并不适合我的情况。特别是因为我无法使用prev()函数将指针移回。所以我确实实现了Iterator Interface并相应地覆盖了nextprev方法。

因此,当调用next()并且它在数组的末尾时,它会将指针倒回到开头,同样,如果调用prev()并且指针已经在开头,它会将指针移动到结尾内部数组。这对我很有用。

相关代码

<?php

class CircularIterator implements Iterator
{
    ...
    ...
    public function next()
    {
        next($this->entries);
        if (!$this->current()) {
            $this->rewind();
        }
    }

    public function prev()
    {
        prev($this->entries);
        if (!$this->current()) {
            $this->end();
        }
    }
  ....
  ....
}

完整的实现和示例代码 - Link

© www.soinside.com 2019 - 2024. All rights reserved.