2013-04-29 72 views
18

我有一個名爲Collection的類,它存儲相同類型的對象。 Collection實現陣列接口:IteratorArrayAccessSeekableIterator,並Countablearray_map與數組接口的集合?

我想傳遞一個Collection對象作爲數組參數到array_map功能。但這種失敗,出現錯誤

PHP的警告:array_map():參數#2應該是一個數組

我可以通過實施其他/多接口實現這一目標,使Collection對象被看作數組?

+3

推出自己的collection_map功能? – Adder 2013-04-29 08:21:05

+0

@Adder Course我可以,但現在我正在尋找解決方案,如果我可以使用我的集合與buildin php funcs :) – f1ames 2013-04-29 08:28:23

回答

6

array_map想要,顧名思義,陣列。畢竟它不叫iterator_map。 ;)

除了生成一個潛在的大型臨時數組的iterator_to_array()之外,沒有技巧使得可迭代對象可以使用array_map

Functional PHP庫有map實現其在可迭代的收集工作。

+0

功能PHP映射實現不是有效的內存:結果存儲在數組中。我找到了一個更好的庫:https://github.com/SuRaMoN/itertools還有一篇博客文章解釋瞭如何自己構建它:http://www.a-basketful-of-papayas.net/2012/07/what -adrators-can-do-for-you.html – 2015-07-27 16:33:16

+0

Aad,通常map函數的結果是* new *數組 - 內存開銷與方法是固有的,在絕大多數用例中可忽略不計。 – 2016-11-01 19:01:38

+0

「使用'array_map'使可迭代對象工作沒有任何竅門。」這個技巧是'iterator_to_array()'。 – 2017-05-12 16:13:42

19

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

這是行不通的,但會有性能損失,因爲它會在iterator_to_array步驟中迭代,並且會在array_map步驟中再次迭代。 – 2014-01-30 18:15:40

+1

@EelkevandenBos我在答案中給出了兩個解決方案,後者沒有展示這種「性能損失」;除此之外,在這兩種情況下,運行時間都是O(n)。 – 2014-01-30 23:26:30

2

我想出了以下解決方案:

//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

如果你是而不是有興趣創建一個新的數組,這是一個函數映射到原始數組,你可以使用foreach循環(因爲你實現Iterator)。

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

如果你真的想使用地圖,那麼我認爲你必須實現自己的。我建議做它收集的方法,如:

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

我會問自己,如果你真的想用map或者你真的只是意味着foreach