2012-01-04 9 views
4

私は、レンダリングされる要素オブジェクトをコンテナに格納するSplObjectStorageインスタンスを持っています。私は効率的に店舗内の任意の場所からオブジェクトを追加したり削除したりできます。SplObjectStorageインスタンスの子を再構成する

例:

<?php 
$store = new SplObjectStorageWrapper; 
$obj1 = new Obj; 
$obj2 = new Obj; 
$obj3 = new Obj; 

$store->attach($obj1); 
$store->attach($obj2); 
$store->insertAtIndex($obj3, 1); 

//Storage should now be organized as $obj1, $obj3, $obj2 

どのように私はinsertAtIndexメソッドを実装するに行きますか?特定の位置の後に子供を切り離して再接続するにはLimitIteratorを使用しますか?配列ベースのオブジェクトストレージを使用すると、SplObjectStorageインスタンスよりもはるかに遅いことが判明しました。私が実装したい

他の方法は、それがこれを行う最も簡単な(と明らかに最も効率的な)方法はSplObjectStorageを延長するとLimitIteratorを利用することで判明removeAtIndex(integer)indexOf(object)

+0

SplObjectStorageのSet部分が必要ですか?重複はありませんか?そうでない場合は、代わりにSplPriorityQueueクラスを試してください。 'insertAt'とまったく同じ働きはしませんが、あなたのユースケースには十分かもしれません。 – Gordon

+0

ゴードン、そうではありません。しかし、パフォーマンスの大きな違いのために、アレイベースのソリューションの代わりにSplObjectStorageを使用する必要があります。 – Kenaniah

答えて

3

が含まれます。以下のコード例:

<?php 
/** 
* Extends the SplObjectStorage class to provide index functions 
*/ 
class ObjectStorage extends SplObjectStorage { 

    /** 
    * Returns the index of a given object, or false if not found 
    * @param object $object 
    */ 
    function indexOf($object){ 

     if(!$this->contains($object)) return false; 

     foreach($this as $index => $obj) if($obj === $object) return $index; 

    } 

    /** 
    * Returns the object at the given index 
    */ 
    function itemAtIndex($index){ 

     $it = new LimitIterator($this, $index, 1); 
     foreach($it as $obj) return $obj; 

    } 

    /** 
    * Returns the sequence of objects as specified by the offset and length 
    * @param int $offset 
    * @param int $length 
    */ 
    function slice($offset, $length){ 

     $out = array(); 
     $it = new LimitIterator($this, $offset, $length); 
     foreach($it as $obj) $out[] = $obj; 
     return $out; 

    } 

    /** 
    * Inserts an object (or an array of objects) at a certain point 
    * @param mixed $object A single object or an array of objects 
    * @param integer $index 
    */ 
    function insertAt($object, $index){ 

     if(!is_array($object)) $object = array($object); 

     //Check to ensure that objects don't already exist in the collection 
     foreach($object as $k => $obj): 
      if($this->contains($obj)) unset($object[$k]); 
     endforeach; 

     //Do we have any objects left? 
     if(!$object) return; 

     //Detach any objects at or past this index 
     $remaining = array(); 
     if($index < $this->count()): 
      $remaining = $this->slice($index, $this->count() - $index); 
      foreach($remaining as $obj) $this->detach($obj); 
     endif; 

     //Add the new objects we're splicing in 
     foreach($object as $obj) $this->attach($obj); 

     //Attach the objects we previously detached 
     foreach($remaining as $obj) $this->attach($obj); 

    } 

    /** 
    * Removes the object at the given index 
    * @param integer $index 
    */ 
    function removeAt($index){ 

     $this->detach($this->itemAtIndex($index)); 

    } 

} 
関連する問題