0

ネストされたオブジェクトをツリーとして処理するために RecursiveArrayIterators をいじっています。次のコードは、結果が期待する値の一部しか返さないため、気になります。主に、ルートノードは決して繰り返されないようです。少し長く見つめすぎたような気がしますが、これで正しい軌道に乗っていることを確認したかったのです.

class Container extends \RecursiveArrayIterator
{
    protected $_alias;

    public function __construct( $alias = null )
    {
        if( is_null( $alias ) )
        {
            $alias = uniqid( 'block_' );
        }

        $this->_alias = $alias;
    }

    public function getAlias()
    {
        return $this->_alias;
    }
}

try
{
    $root = new Container( 'root_level' );
    $block = new Container( 'first_level' );
    $child = new Container( 'second_level' );
    $child_of_child_a = new Container( 'third_level_a' );
    $child_of_child_b = new Container( 'third_level_b' );

    $child->append( $child_of_child_a );
    $child->append( $child_of_child_b );
    $child_of_child_a->append( new Container );
    $child_of_child_a->append( new Container );
    $block->append( $child );
    $root->append( $block );

    $storage = new \RecursiveIteratorIterator( $root, RecursiveIteratorIterator::SELF_FIRST );

    foreach( $storage as $key => $value )
    {
        print_r( str_repeat( ' ', $storage->getDepth() * 4 ) . $value->getAlias() . PHP_EOL );
    }
}
catch( \Exception $e )
{
    var_dump( $e->getMessage() );
}

という結果に・・・

first_level
second_level
    third_level_a
        block_51f98b779c107
        block_51f98b779c124
    third_level_b

ルート ノードはどこにありますか?

答え

Sven の答えは、これを正しく処理するために過労した私の脳を混乱させました。これは、他の誰かが同様のことを試みている場合に備えて、成功したコードの最後のビットです。

class OuterContainer extends \ArrayIterator
{

}

class Container extends \ArrayIterator
{
    protected $_alias;

    public function __construct( $alias = null )
    {
        if( is_null( $alias ) )
        {
            $alias = uniqid( 'container_' );
        }

        $this->_alias = $alias;
    }

    public function getAlias()
    {
        return $this->_alias;
    }
}

try
{
    $c1 = new Container( 'Base' );

    $c1_c1 = new Container( 'Base > 1st Child' );

    $c1_c2 = new Container( 'Base > 2nd Child' );

    $c1_c1_c1 = new Container( 'Base > 1st Child > 1st Child' );

    $c1_c1->append( $c1_c1_c1 );

    $c1->append( $c1_c1 );

    $c1->append( $c1_c2 );

    $outer_container = new OuterContainer;

    $outer_container->append( $c1 );

    $storage = new \RecursiveIteratorIterator( new \RecursiveArrayIterator( $outer_container ), RecursiveIteratorIterator::SELF_FIRST );

    foreach( $storage as $key => $value )
    {
        print_r( $value->getAlias() . PHP_EOL );
    }
}
catch( \Exception $e )
{
    var_dump( $e->getMessage() );
}
4

1 に答える 1

1

RecursiveArrayIterator を正しく使用していないため、ルート ノードは存在しません。

使用目的は、任意のレベルと構造に複数のサブ配列を持つ配列を持ち、この配列を RecursiveArrayIterator の 1 つのインスタンスに渡し、すべてを反復処理して、これを RecursiveIteratorIterator に入れることです。

そうすれば、トップレベルを含む配列全体が反復されます。

RecursiveArrayIterator を情報のキャリアとして悪用したため、最上位オブジェクトは反復されません。

やや厄介ですが、原則を示す簡単な例を提案します。

$root = array( 'root_level' );
$block = array( 'first_level' );
$child = array( 'second_level' );
$child_of_child_a = array( 'third_level_a' );
$child_of_child_b = array( 'third_level_b' );

$child[] = $child_of_child_a;
$child[] = $child_of_child_b ;
$child_of_child_a[] = array('');
$child_of_child_a[] = array('');
$block[] = $child;
$root[] = $block ;

$storage = new \RecursiveIteratorIterator( new \RecursiveArrayIterator($root), RecursiveIteratorIterator::SELF_FIRST );

var_dump($root);
foreach ($storage as $key=>$value) {
    echo $key.": ".$value."\n";
}

結果出力:

array(2) {
    [0] =>
  string(10) "root_level"
  [1] =>
  array(2) {
        [0] =>
    string(11) "first_level"
    [1] =>
    array(3) {
            [0] =>
      string(12) "second_level"
      [1] =>
      array(1) {
                ...
            }
      [2] =>
      array(1) {
                ...
            }
    }
  }
}
0: root_level
1: Array
    0: first_level
1: Array
    0: second_level
1: Array
    0: third_level_a
2: Array
    0: third_level_b

出力はまったく同じではありませんが、私の要点は、すべてのノードを RecursiveArrayIterator のインスタンスにすることなく、構造を反復処理できるということです。配列、配列として機能するオブジェクト、または便利に反復できるオブジェクトのいずれかを追加できます。

于 2013-07-31T22:35:17.483 に答える