3

I have an array which looks something like this:

$a = [
    1 => [
        'title' => 'test',
        'items' => [
            5 => [
                'title' => 'hello',
                'items' => []
            ]
        ]
    ],
    2 => [
        'title' => 'second',
        'items' => [
            7 => [
                'title' => 'hello in second',
                'items' => []
            ]
        ]
    ],
    3 => [
        'title' => 'third',
        'items' => [
            10 => [
                'title' => 'hello in third',
                'items' => []
            ]
        ]
    ],
];

I need a way to extract parts of it by key no matter where they are in the tree. I've tried several ways but I'm not sure how efficient they are. If it helps I need to extract only those parts which have a numeric key. Any help will be much appreciated.

Vladimir
  • 818
  • 5
  • 13
  • Do you need only the biggest sub-array with a numerical key, or every part that has a numerical key? for example, you top level array's every key is numerical, and some sub-sub-array's keys are too. Do you want only the top-level arrays inside the results alone, or with the sub-sub-arrays alongside them (even if some other result contains those inside them somewhere)? – complex857 Nov 22 '12 at 20:32
  • 2
    Bad design smell. Organize your code in objects, then you can filter the collections the way you want. – moonwave99 Nov 22 '12 at 20:33
  • @complex857 I need to get the parts with numeric key. They're either on the top level on nested inside in an 'items' array. But there can be unlimited nesting. – Vladimir Nov 22 '12 at 20:40
  • Take a look at [this answer](http://stackoverflow.com/questions/1019076/how-to-search-by-key-value-in-a-multidimensional-array-in-php) – Nathan Kot Nov 22 '12 at 20:41

1 Answers1

3

Try using the SPL iterators:

class KeyFinderFilterIterator extends FilterIterator {
    private $search = null;
    public function __construct($iterator, $search) {
        $this->search = $search;
        parent::__construct($iterator);
    }
    public function accept(){
        return $this->key() == $this->search;
    }
}

 $it = new KeyFinderFilterIterator(
      new RecursiveIteratorIterator(
           new RecursiveArrayIterator($a), 
           RecursiveIteratorIterator::SELF_FIRST
      ), 
      10
 );

foreach ($it as $key => $value) {
    var_dump($value);
}
complex857
  • 20,425
  • 6
  • 51
  • 54
  • Very good solution, thank you. I am assuming that it's the fastest way possible. Just one final thing - can I get the value without using foreach? Thank in advance. – Vladimir Nov 22 '12 at 21:11
  • Sure, just call the `next` on the iterator and the first match should be returned by the `current` method after that. – complex857 Nov 22 '12 at 21:16
  • Thanks again, you saved me a lot of time. – Vladimir Nov 22 '12 at 21:27