Multidimensional array iteration

匿名 (未验证) 提交于 2019-12-03 01:18:02

问题:

Say you have the following array:

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

How would you go about transforming it to an XML string so that it looks like:

parent nodeparent nodechild nodechild nodegrand child nodegrand child node

One way to do it would be through a recursive method like:

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

I'm looking for an approach that uses iteration, though.

回答1:

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


回答2:

You could use an Iterator to iterate over the array and then produce your desired output:

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

and then assemble it like this:

$iterator = new TranformArrayIterator(new RecursiveArrayIterator($nodes));  foreach($iterator as $val) {     echo $val; } 

outputs

parent nodeparent nodechild nodechild nodegrand child nodegrand child node

To blank out $key when using $key => $val, add this to TraverseArrayIterator

public function key() {      return ''; } 

Since your aim seems to be to produce XML, you could also pass an XMLWriter as a collaborator to the Iterator. This allows for more control over the generated XML and also makes sure the output is valid XML:

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());     } } 

You'd then use it like this:

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

and foreach'ing over it will produce the same output then (but adding the XML prolog)



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!