同じタイプのオブジェクトを格納するCollection
というクラスがあります。 Collection
は配列インターフェイスを実装します:Iterator
、ArrayAccess
、SeekableIterator
、およびCountable
。
Collection
オブジェクトを配列引数として array_map
関数に渡したいのですが。しかし、これはエラーで失敗します
PHP警告:array_map():引数#2は配列である必要があります
Collection
オブジェクトが配列として表示されるように、他の/より多くのインターフェイスを実装することでこれを実現できますか?
array_map()
関数は、配列引数としてTraversable
をサポートしていないため、変換手順を実行する必要があります。
_array_map($fn, iterator_to_array($myCollection));
_
コレクションを2回繰り返し処理するだけでなく、後で使用されない配列も生成します。
もう1つの方法は、独自のマップ関数を作成することです。
_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
_は、名前が示すように、arraysを必要とします。結局、それは_iterator_map
_と呼ばれるわけではありません。 ;)
潜在的に大きな一時配列を生成するiterator_to_array()
を除いて、反復可能オブジェクトを_array_map
_で動作させるトリックはありません。
Functional PHP ライブラリには、反復可能なコレクションで機能するmap
実装があります。
notが、元の配列にマップされた関数である新しい配列の作成に興味がある場合は、foreachループを使用できます(Iterator
を実装しているため)。
foreach($item in $myCollection) {
$item->method1();
$item->method2();
}
実際にマップを使用したい場合は、独自に実装する必要があると思います。コレクションのメソッドにすることをお勧めします。例:
$mutatedCollection = $myCollection->map(function($item) {
/* do some stuff to $item */
return $item;
});
あなたが本当にmap
を使いたいのか、それともforeach
私は次の解決策を思いつきました:
//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);
このようにして、次のようなアプローチの場合のように2回繰り返すことなく配列を生成できます。
$iterator = new ArrayIterator(array(1,2,3));
$array = iterator_to_array($iterator); //first iteration
$output = array_map(function() {}, $array); //second iteration
幸運を!
私はこの質問に遭遇しただけで、コレクションを配列にキャストして機能させることができました。
array_map($cb, (array) $collection);
免責事項元の質問の場合、これは適切なオプションではない可能性がありますが、この解決策で解決した問題を解決しようとしているときに質問を見つけました。可能/実行可能な場合は、カスタムイテレータマップを使用することをお勧めします。
別のオプションは次のようなことをすることです:
foreach($collection as &$item) {
$item = $cb($item);
}
基になるコレクションを変更します。