2

I have the next hierarchy array:

Array(
[1005] => Array(
               [1000] => Array(
                              [1101] => ...
                              [1111] => ...
                              )
               )
)

In my function I send $Id. And my task to return a array by this Id. For example: getArray(1000) should return the next array:

Array(
                                  [1101] => ...
                                  [1111] => ...
                                  )

How can I make this? Thanks.

Alex Pliutau
  • 21,392
  • 27
  • 113
  • 143
  • Medoo? http://stackoverflow.com/questions/3776798/php-array-recursion – Wernight Sep 23 '10 at 09:52
  • In my answer at http://stackoverflow.com/questions/3776798/php-array-recursion you could actually just keep the `$paths` array and get any node with `$paths[$id]`. But it appeared to be a _'not very good solution'_ for unknown reasons. It would however solve the problem directly, and even that: with no duplicate data, and just 1 single loop through the nodes in the entire thing. – Wrikken Sep 23 '10 at 13:13

2 Answers2

5

Here is a recursive implementation of getArray:

function getArray($array, $index) {
    if (!is_array($array)) return null;
    if (isset($array[$index])) return $array[$index];
    foreach ($array as $item) {
        $return = getArray($item, $index);
        if (!is_null($return)) {
            return $return;
        }
    }
    return null;
}

And here is an iterative implementation of getArray:

function getArray($array, $index) {
    $queue = array($array);
    while (($item = array_shift($queue)) !== null) {
        if (!is_array($item)) continue;
        if (isset($item[$index])) return $item[$index];
        $queue = array_merge($queue, $item);
    }
    return null;
}
Gumbo
  • 643,351
  • 109
  • 780
  • 844
3

And an answer that uses the recursive iterator:

function getArray($array, $index) {
    $arrayIt = new RecursiveArrayIterator($array);
    $it = new RecursiveIteratorIterator(
        $arrayIt, 
        RecursiveIteratorIterator::SELF_FIRST
    );
    foreach ($it as $key => $value) {
        if ($key == $index) {
            return $value;
        }
    }
    return null;
}

Or, if you really want to get fancy, you could use a filter iterator:

class IndexFilterIterator extends FilterIterator {
    protected $index = '';
    public function __construct($iterator, $index) {
        $this->index = $index;
        parent::__construct($iterator);
    }
    public function accept() {
        return parent::key() == $index;
    }
}

function getArray($array, $index) {
    $arrayIt = new RecursiveArrayIterator($array);
    $it = new RecursiveIteratorIterator(
        $arrayIt, 
        RecursiveIteratorIterator::SELF_FIRST
    );
    $filterIt = new IndexFilterIterator($it, $index);
    $filterIt->rewind();
    if ($filterIt->valid()) {
        return $filterIt->current();
    }
    return null;
}
ircmaxell
  • 163,128
  • 34
  • 264
  • 314