我有一个名为的类Collection
,它存储相同类型的对象。
Collection
实现数组接口:Iterator
、ArrayAccess
、SeekableIterator
和Countable
.
我想将一个Collection
对象作为数组参数传递给array_map
函数。但这失败并出现错误
PHP 警告:array_map():参数 #2 应该是一个数组
我可以通过实现其他/更多接口来实现这一点,以便将Collection
对象视为数组吗?
该array_map()
函数不支持 aTraversable
作为其数组参数,因此您必须执行转换步骤:
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
适用于任何可迭代集合的实现。
如果您对创建一个映射在原始数组上的函数的新数组不Iterator
感兴趣,则可以只使用 foreach 循环(因为您实现了)。
foreach($item in $myCollection) {
$item->method1();
$item->method2();
}
如果你真的想使用地图,那么我认为你必须实现自己的。我建议将其作为 Collection 上的一种方法,例如:
$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);
这样,您可以生成一个数组,而无需像使用以下方法那样迭代两次:
$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);
}
这将改变基础集合。
编辑:
有人指出,强制转换为数组可能会产生不必要的副作用。最好向您的集合添加一个方法以从迭代器返回数组并遍历它,或者添加一个map
接受回调并在底层迭代器上运行循环的方法。