array_map для коллекции с интерфейсами массива?

У меня есть класс под названием Collection который хранит объекты того же типа. Collection реализует интерфейсы массивов: Iterator , ArrayAccess , SeekableIterator и Countable .

Я хотел бы передать объект Collection в качестве аргумента array_map функции array_map . Но это не удается с ошибкой

PHP Предупреждение: array_map (): Аргумент # 2 должен быть массивом

Могу ли я достичь этого, реализуя другие / дополнительные интерфейсы, чтобы объекты Collection рассматривались как массивы?

    Функция array_map() не поддерживает Traversable качестве аргумента массива, поэтому вам нужно будет выполнить шаг преобразования:

     array_map($fn, iterator_to_array($myCollection)); 

    Помимо повторной обработки коллекции дважды, она также дает массив, который впоследствии не будет использоваться.

    Другой способ – написать собственную функцию карты:

     function map(callable $fn) { $result = array(); foreach ($this as $item) { $result[] = $fn($item); } return $result; } 

    Обновить

    Судя по вашему делу, кажется, что вас даже не интересует результат операции с картой; поэтому имеет смысл использовать iterator_apply() .

     iterator_apply($myCollection, function($obj) { $obj->method1(); $obj->method2(); return true; }); 

    array_map хочет, как следует из названия, массивов . В конце концов, он не называется iterator_map . 😉

    Помимо iterator_to_array() , который создает потенциально большой временный массив, нет никакого трюка, чтобы сделать итерационные объекты работать с array_map .

    Функциональная библиотека PHP имеет реализацию map которая работает в любой итеративной коллекции.

    Я придумал следующее решение:

     //lets say you have this iterator $iterator = new ArrayIterator(array(1, 2, 3)); //and want to append the callback output to the following variable $out = []; //use iterator to apply the callback to every element of the iterator iterator_apply( $iterator, function($iterator, &$out) { $current = $iterator->current(); $out[] = $current*2; return true; }, array($iterator, &$out) //arguments for the callback ); print_r($out); 

    Таким образом, вы можете сгенерировать массив без повторения дважды, как вам хотелось бы с таким подходом, как:

     $iterator = new ArrayIterator(array(1,2,3)); $array = iterator_to_array($iterator); //first iteration $output = array_map(function() {}, $array); //second iteration 

    Удачи!

    Если вы не заинтересованы в создании нового массива, который является функцией, сопоставленной с исходным массивом, вы можете просто использовать цикл foreach (потому что вы реализуете Iterator ).

     foreach($item in $myCollection) { $item->method1(); $item->method2(); } 

    если вы действительно хотите использовать карту, то я думаю, вам придется реализовать свои собственные. Я бы предложил сделать его методом в коллекции, например:

     $mutatedCollection = $myCollection->map(function($item) { /* do some stuff to $item */ return $item; }); 

    Я хотел бы спросить себя, действительно ли вы хотите использовать map или вы действительно просто означаете foreach