反转SPLObjectStorage

反转SPLObjectStorage

问题描述:

I have an SPLObjectStorage object with a Player object as the key and score as the info associated with it. The player objects get added to the storage in order from highest to lowest score, but I'm now to a point where I need to iterate through them in reverse order.

I also need to be able to loop all the way through starting from a specified offset. I've figured this part out below, I just can't figure out a good way to reverse it first.

// $players_group = new SPLObjectStorage()
// code to add Player and Score would go here
// above lines just for example

# NEED TO REVERSE ORDER PLAYERS GROUP HERE

$infinite_it = new InfiniteIterator($players_group);
$limit_it = new LimitIterator($infinite_it, $current_offset, $players_group->count());
foreach($limit_it as $p){
    // properly outputting from offset all the way around
    // but I need it in reverse order
}

I would like to avoid having to loop through the storage object and push all of them into an array, then do array_reverse, and then finally proceed with my foreach loop.

我有一个SPLObjectStorage对象,其中一个Player对象作为键,并得分为与之关联的信息。 玩家对象按照从最高到最低的分数顺序添加到存储中,但现在我需要以相反的顺序迭代它们。 p>

我还需要能够从指定的偏移量开始循环。 我已经在下面找到了这个部分,我只是想不出一个好的方法来先扭转它。 p>

  // $ players_group = new SPLObjectStorage()
 //添加播放器和分数的代码将在此处
 //以上行仅为例如
 
# 需要在这里反击玩家组
 
 $ infinite_it = new InfiniteIterator($ players_group); 
 $ limit_it = new LimitIterator($ infinite_it,$ current_offset,$ players_group-> count()); 
foreach($ limit_it 作为$ p){
 //正确地从偏移输出正确地输出
 //但是我需要它以相反的顺序
} 
  code>  pre> 
 
 

我会 喜欢避免不得不遍历存储对象并将它们全部推入数组,然后执行array_reverse,最后继续我的foreach循环。 p> div>

SplObjectStorage is a key->value store and The "key" of an element in the SplObjectStorage is in fact the hash of the object. Sorting and Reverting would require you to extend and write your own implementation but i think you should consider Using SplStack

Imagine your player class

class Player {
    private $name;
    function __construct($name) {
        $this->name = $name;
    }
    function __toString() {
        return $this->name;
    }
}

Using SplStack

$group = new SplStack();
$group->push(new Player("Z"));
$group->push(new Player("A"));
$group->push(new Player("B"));
$group->push(new Player("C"));

echo "<pre>";
$infinite_it = new InfiniteIterator($group);
$limit_it = new LimitIterator($infinite_it, 0, 3); // get frist 3
foreach ( $limit_it as $p ) {
    echo ("$p");
}

If you insist on SplObjectStorage then you can consider a custom ReverseArrayIterator

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

Usage

$group = new SplObjectStorage();
$group->attach(new Player("Z"));
$group->attach(new Player("A"));
$group->attach(new Player("B"));
$group->attach(new Player("C"));

echo "<pre>";
$infinite_it = new InfiniteIterator(new ReverseArrayIterator($group));
$limit_it = new LimitIterator($infinite_it, 0, 3); // get frist 3
foreach ( $limit_it as $p ) {
    echo ("$p");
}

Both would Output

CBA //reversed 

I would like to avoid having to loop through the storage object and push all of them into an array, then do array_reverse, and then finally proceed with my foreach loop.

Don't know if it is the most efficient way but as SplObjectStorage implements Iterator you can use iterator_to_array and then reverse the array :

array_reverse(iterator_to_array($players_group));