我希望无限地像一个圆形数组。
我使用InfiniteIterator
1进行以下设置,它无限地迭代$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()
返回当前项目,(意思是,它在逻辑中正常工作)
如果不是使用迭代器,你可以使用一个数组和一个指向'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;
}
您可以使用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。
发布我最终提出的答案。
无限迭代器并不适合我的情况。特别是因为我无法使用prev()
函数将指针移回。所以我确实实现了Iterator Interface并相应地覆盖了next
和prev
方法。
因此,当调用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