2010-02-05 7 views
2

는 다음과 같은 배열을 말해봐다차원 배열을 반복

function traverse($nodes) 
{ 
    echo "<node>"; 

    foreach($nodes as $node) 
    { 
     if(is_array($node)) 
     { 
      traverse($node); 
     } 
     else 
     { 
      echo "<node>$node</node>"; 
     } 
    } 

    echo "</node>"; 
} 

traverse($nodes); 

나는 반복을 사용하는 접근법을 찾고 있는데, 그래도. 이런 식으로 조립 한 후

class TranformArrayIterator extends RecursiveIteratorIterator 
{ 
    protected function indent() 
    { 
     echo str_repeat("\t", $this->getDepth()); 
     return $this; 
    } 
    public function beginIteration() 
    { 
     echo '<nodes>', PHP_EOL; 
    } 
    public function endIteration() 
    { 
     echo '</nodes>', PHP_EOL; 
    } 
    public function beginChildren() 
    { 
     $this->indent()->beginIteration(); 
    } 
    public function endChildren() 
    { 
     $this->indent()->endIteration(); 
    } 
    public function current() 
    { 
     return sprintf('%s<node>%s</node>%s', 
         str_repeat("\t", $this->getDepth() +1), 
         parent::current(), 
         PHP_EOL); 
    } 
} 

과 :

+0

왜 반복 기반 방식을 찾고 있습니까? 숙제인가요? – SilentGhost

+0

왜? 왜 그럴거야? –

+0

예제에서는 이미 반복을 반복과 함께 사용합니다. – meagar

답변

2
<?php 

$nodes = array(
    "parent node", 
    "parent node", 
    array(
     "child node", 
     "child node", 
     array(
      "grand child node", 
      "grand child node" 
     ) 
    ) 
); 

$s = '<node>'; 
$arr = $nodes; 

while(count($arr) > 0) 
{ 
    $n = array_shift($arr); 
    if(is_array($n)) 
    { 
     array_unshift($arr, null); 
     $arr = array_merge($n, $arr); 
     $s .= '<node>'; 
    } 
    elseif(is_null($n)) 
     $s .= '</node>'; 
    else 
     $s .= '<node>'.$n.'</node>'; 
} 
$s .= '</node>'; 

echo $s; 

?> 
+0

Brilliant! 이것이 재귀 기반 접근법보다 빠르지는 모르겠습니다. –

15

당신은 배열을 반복하는 Iterator를 사용하고 원하는 출력을 생산할 수

$iterator = new TranformArrayIterator(new RecursiveArrayIterator($nodes)); 

foreach($iterator as $val) { 
    echo $val; 
} 

출력

<nodes> 
     <node>parent node</node> 
     <node>parent node</node> 
     <nodes> 
       <node>child node</node> 
       <node>child node</node> 
       <nodes> 
         <node>grand child node</node> 
         <node>grand child node</node> 
       </nodes> 
     </nodes> 
</nodes> 

공백을 넣으려면 $key를 사용할 때 당신의 목표는 XML을 생성하는 것으로 보인다 때문에은 또한 반복자에 협력자로서 XMLWriter가를 전달할 수, TraverseArrayIterator

public function key() 
{ 
    return ''; 
} 

이를 추가 할 수 있습니다. 이렇게 생성 된 XML을보다 제어 할 수 있으며 출력이 유효한 XML입니다 확인합니다 :

$xmlWriter = new XmlWriter; 
$xmlWriter->openUri('php://output'); 
$xmlWriter->setIndent(true); 
$xmlWriter->setIndentString("\t"); 
$iterator = new TranformArrayIterator(
    $xmlWriter, 
    new RecursiveArrayIterator($nodes) 
); 

foreach '가 생산됩니다를 통해 보내고을 :

class TranformArrayIterator extends RecursiveIteratorIterator 
{ 
    private $xmlWriter; 

    public function __construct(
     XmlWriter $xmlWriter, 
     Traversable $iterator, 
     $mode = RecursiveIteratorIterator::LEAVES_ONLY , 
     $flags = 0) 
    { 
     $this->xmlWriter = $xmlWriter; 
     parent::__construct($iterator, $mode, $flags); 
    } 

    public function beginIteration() 
    { 
     $this->xmlWriter->startDocument('1.0', 'utf-8'); 
     $this->beginChildren(); 
    } 
    public function endIteration() 
    { 
     $this->xmlWriter->endDocument(); 
    } 
    public function beginChildren() 
    { 
     $this->xmlWriter->startElement('nodes'); 
    } 
    public function endChildren() 
    { 
     $this->xmlWriter->endElement(); 
    } 
    public function current() 
    { 
     $this->xmlWriter->writeElement('node', parent::current()); 
    } 
} 

당신은 다음과 같이 사용할 것 동일한 결과가 출력됩니다 (XML 프롤로그 추가)

관련 문제