我有一个名为Collection
的类,它存储相同类型的对象。
Collection
实现了数组接口:Iterator
,ArrayAccess
,SeekableIterator
和Countable
。
我想将Collection
对象作为数组参数传递给array_map
函数。但这失败了,错误
PHP警告:array_map():参数#2应该是一个数组
我可以通过实现其他/更多接口来实现这一点,以便将Collection
个对象视为数组吗?
答案 0 :(得分:25)
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;
});
答案 1 :(得分:7)
array_map
想要数组。毕竟它不叫iterator_map
。 ;)
除了产生可能很大的临时数组的iterator_to_array()
之外,没有办法让可迭代对象与array_map
一起工作。
Functional PHP库有map
实现,适用于任何可迭代集合。
答案 2 :(得分:3)
我提出了以下解决方案:
//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
祝你好运!
答案 3 :(得分:3)
如果您不对创建一个映射到原始数组的函数的新数组感兴趣,则可以使用foreach循环(因为您实现了Iterator
)
foreach($item in $myCollection) {
$item->method1();
$item->method2();
}
如果您真的想使用地图,那么我认为您必须实施自己的地图。我建议将它作为Collection的方法,例如:
$mutatedCollection = $myCollection->map(function($item) {
/* do some stuff to $item */
return $item;
});
我会问你自己是否真的想使用map
或者你真的只是想foreach
答案 4 :(得分:-1)
我偶然发现了这个问题,并设法将集合转换为数组以使其起作用:
array_map($cb, (array) $collection);
免责声明对于最初的问题,这可能不是一个合适的选择,但我在寻找解决该问题的方法时发现了该问题。我建议在可能/可行的情况下使用自定义迭代器映射。
另一种选择是执行以下操作:
foreach($collection as &$item) {
$item = $cb($item);
}
这将使基础集合发生变异。
编辑:
已经指出,强制转换为数组会产生有害的副作用。最好在集合中添加一个方法以从迭代器返回数组,然后遍历该方法,或者添加一个map
方法来接受回调并在基础迭代器上运行循环。