Waiting for Dev...
Waiting for Dev...

Reputation: 13037

kind of iterator_to_array for a recursive iterator to get a bi-dimensional array

when using iterators in PHP you can use iterator_to_array function to kind of extract the array resulting of iterating. For example, let's say you have following ArrayObject:

$array_object = new ArrayObject(array(
   array('1', '2', '3', '4'),
   array('5', '6', '7', '8'),
   array('9', '10', '11', '12'),
));

As you see, its storage is a bi-dimensional array.

We can crete a FilterOperator to only accept its first item (I know it would be better with LimitIterator, it's just as an example purpose):

class myFilterIterator extends FilterIterator
{
   public function accept()
   {
      return ($this->key() === 0);
   }
}

$filter_iterator = new myFilterIterator(new ArrayIterator($array_object));

Now, if i do:

print_r(iterator_to_array($filter_iterator));

I get the array I could get if I manually loop through the operator:

Array ( [0] => Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 ) )

But what now if I want to work with a RecursiveFilterIterator? Let's say I have:

class myRecursiveFilterIterator extends RecursiveFilterIterator
{
   public function accept()
   {
      return ($this->hasChildren() || $this->key() === 0);
   }
}

$recursive_filter_iterator = new myRecursiveFilterIterator(new RecursiveArrayIterator($array_object));

As you see, this will accept only key 0 for each array contained in the parent array. And so it works if I recursive iterate over it:

foreach (new RecursiveIteratorIterator($recursive_filter_iterator) as $value) {
   print_r($value);
   echo '<br />';
}

Results in:

1
5
9

But, how could I get quickly the array array(array(1), array(5), array(9)) ?

If I do:

print_r(iterator_to_array($recursive_filter_iterator));

or

print_r(iterator_to_array($recursive_filter_iterator->getInnerIterator()));

or

$it = new RecursiveIteratorIterator($recursive_filter_iterator);
print_r(iterator_to_array($it->getInnerIterator()));

I get whole original array:

Array ( [0] => Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 ) [1] => Array ( [0] => 5 [1] => 6 [2] => 7 [3] => 8 ) [2] => Array ( [0] => 9 [1] => 10 [2] => 11 [3] => 12 ) )

If I do:

print_r(iterator_to_array(new RecursiveIteratorIterator($recursive_filter_iterator)));

I get just first item:

Array ( [0] => 9 )

If I do:

print_r(iterator_to_array(new RecursiveIteratorIterator($recursive_filter_iterator->getInnerIterator())));

I get last item in my parent array but with key 0:

Array ( [0] => 9 [1] => 10 [2] => 11 [3] => 12 ) 

What I need is to get the array:

Array ( [0] => Array ( [0] => 1 ) [1] => Array ( [0] => 5 ) [2] => Array ( [0] => 9 ) ) 

I know I can get it manually looping, but I want to know if there is a direct way, like in iterator_to_array for not recursive iterators. Sure there is something I don't understand about recursive iterators in PHP, but its documentation is really bad in this.

Thank you very much.

Upvotes: 5

Views: 2084

Answers (3)

salathe
salathe

Reputation: 51950

It is not entirely clear what you are really wanting to do, but the following takes a RecursiveArrayIterator (note: ArrayObject is not a recursive iterator) and uses iterator_to_array() to get the resulting array that you want.

class FirstOnlyRecursiveArrayIterator extends ParentIterator {
    public function __construct(RecursiveArrayIterator $it) {
         parent::__construct($it);
    }
    public function current() {
        $children = parent::current();
        return array_slice($children, 0, 1);
    }
}

$array_it = new RecursiveArrayIterator(array(
    array('1', '2', '3', '4'),
    array('5', '6', '7', '8'),
    array('9', '10', '11', '12'),
));

$filter_iterator = new RecursiveIteratorIterator(
    new FirstOnlyRecursiveArrayIterator($array_it),
    RecursiveIteratorIterator::SELF_FIRST);
print_r(iterator_to_array($filter_iterator));

Upvotes: 3

cs0lar
cs0lar

Reputation: 377

OK. One easy way could be the following. It extends the ArrayIterator class and overrides the current() function to return the sliced array:

<?php
class FirstOnlyIterator extends ArrayIterator
{
    public function current()
    {
            $next = parent::current();
            return array_slice($next, 0, 1);
    }
}

$array_object = new ArrayObject(array(
     array('1', '2', '3', '4'),
     array('5', '6', '7', '8'),
     array('9', '10', '11', '12'),
));

$iterator = new FirstOnlyIterator($array_object);

print_r(iterator_to_array($iterator));
?>

Upvotes: 0

cs0lar
cs0lar

Reputation: 377

Do you need/want to use iterators? You could use php's built-in array_map() function which takes an array and a function and applies the specified function to each element in the array. So you could do:

<?php
function get_first($foo)
{ 
    return array_slice($foo, 0, 1); //slice the array right after the first element
}

$array_object = new ArrayObject(array(
     array('1', '2', '3', '4'),
     array('5', '6', '7', '8'),
     array('9', '10', '11', '12'),
));

$new_array = array_map("get_first", $array_object->getArrayCopy());
print_r($new_array);
?>

The result will be:

Array
(
    [0] => Array
        (
            [0] => 1
        )

    [1] => Array
        (
            [0] => 5
        )

    [2] => Array
        (
            [0] => 9
        )
)

I apologise if I have misunderstood your question.

Upvotes: 0

Related Questions