2013-10-31 17 views
10

我查看了web中的類似主題以及堆棧溢出,但可以清楚地將這個問題弄清楚。 Difference between array_map, array_walk and array_filterarray_filter()和array_map()之間的區別?

<?php 
error_reporting(-1); 

$arr = array(2.4, 2.6, 3.5); 

print_r(array_map(function($a) { 
    $a > 2.5; 
},$arr)); 

print_r(array_filter($arr, function($a){ 
    return $a > 2.5; 
})); 

?> 

上面的代碼返回我一個過濾數組,其值> 2.5array_filter可以通過array_map來實現嗎?

+0

您是否閱讀過文檔? – sectus

回答

16

所有這三個,array_filterarray_map,和array_walk,以相同的方式使用一個回調函數來循環通過陣列多foreach環使用$key =>$value對通過$array循環。
在這篇文章中,我將把原來的數組傳遞給上述函數,作爲$array(循環中當前項目的索引),如$key,以及當前項目的值在循環中,如$value

array_filter被比作MySQL的SELECT查詢,它選擇記錄但不修改它們。
array_filter的回調函數傳遞當前循環條目的$value,並且回調函數返回的任何內容都被視爲布爾值。
如果爲真,則該項目包含在結果中。
如果false,該項目被排除在結果之外。
因此,你可以這樣做:

<pre><?php 
$users=array('user1'=>array('logged_in'=>'Y'),'user2'=>array('logged_in'=>'N'),'user3'=>array('logged_in'=>'Y'),'user4'=>array('logged_in'=>'Y'),'user5'=>array('logged_in'=>'N')); 
function signedIn($value) 
{ 
    if($value['logged_in']=='Y')return true; 
    return false; 
} 
$signedInUsers=array_filter($users,'signedIn'); 
print_r($signedInUsers);//Array ([user1] => Array ([logged_in] => Y) [user3] => Array ([logged_in] => Y) [user4] => Array ([logged_in] => Y)) 
?></pre> 

array_map,另一方面接受多個陣列作爲參數。 如果指定了一個數組,循環中當前項目的$值將被髮送到回調函數。 如果使用兩個或多個陣列,所有陣列需要首先通過array_values如documentation提到進行傳遞:

如果數組參數包含字符串鍵然後返回的數組 將包含字符串鍵,當且僅如果只有一個數組被傳遞。 如果多於一個參數傳遞然後返回的數組總是具有 整數密鑰

第一陣列是通過環和它的值被傳遞到回調作爲第一個參數,並且如果第二陣列被指定它也將循環播放,其值將作爲第二個參數發送到回調函數,以及其他參數的等等。
如果陣列不匹配的長度,最大陣列被使用,在documentation提到:使用兩個或更多個陣列時

通常,它們應該是相等長度的 因爲回調函數並行應用於相應的元件。如果陣列的長度不等,則較短的 將用空元素進行擴展以匹配最長的長度。

每次調用回調函數時,都會收集返回值。 僅當使用一個數組時,鍵才被保留,並且array_map返回結果數組。 如果使用兩個或多個數組,則鍵將丟失,而是返回一個填充了回調結果的新數組。 array_map只發送回調當前項目的$值而不是它的$ key。 如果您還需要密鑰,則可以將array_keys($array)作爲附加參數傳遞,然後回調將同時接收$ key和$值。
但是,使用多個陣列時,原始鍵將以與array_values放棄鍵相同的方式丟失。 如果您需要保留鍵,您可以使用array_keys來抓取原始數組中的鍵和array_values以獲取array_map的結果中的值,或者直接使用array_map的結果,因爲它已經返回值,然後使用array_combine將兩者結合起來。

因此,你可以做:

<pre><?php 
$array=array('apple'=>'a','orange'=>'o'); 
function fn($key,$value) 
{ 
    return $value.' is for '.$key; 
} 
$result=array_map('fn',array_keys($array),$array); 
print_r($result);//Array ([0] => a is for apple [1] => o is for orange) 
print_r(array_combine(array_keys($array),$result));//Array ([apple] => a is for apple [orange] => o is for orange) 
?></pre> 

array_walk是在回調被髮送兩者鍵和值非常接近的foreach($array as $key=>$value)。如果你想直接傳入第三個參數給回調函數,它也接受一個可選參數。
array_walk返回一個布爾值,指示循環是否成功完成。
(我還沒有找到它的實際用途)
請注意,array_walk不使用回調的返回。 由於array_walk返回一個布爾值,爲了讓array_walk影響某些東西, 您需要引用& $ value,因此您需要修改或使用全局數組。 或者,如果您不想污染全局作用域,則可以使用array_walk的可選第三個參數來傳遞對要寫入的變量的引用。

因此,你可以做:

<pre><?php 
$readArray=array(1=>'January',2=>'February',3=>'March',4=>'April',5=>'May',6=>'June',7=>'July',8=>'August',9=>'September',10=>'October',11=>'November',12=>'December'); 
$writeArray=array(); 
function fn($value,$key,&$writeArray) 
{ 
    $writeArray[$key]=substr($value,0,3); 
} 
array_walk($readArray,'fn',&$writeArray); 
print_r($writeArray);//Array ([1] => Jan [2] => Feb [3] => Mar [4] => Apr [5] => May [6] => Jun [7] => Jul [8] => Aug [9] => Sep [10] => Oct [11] => Nov [12] => Dec) 
?></pre> 
+0

真的很棒的解釋。 array_filter與SQL查詢的類比對我來說真的很明顯,謝謝。在我10多年的PHP中,我幾乎很少使用任何內置的數組函數,所以我現在花時間去探索它們,所以這些例子都很好。我真的認爲很多PHP開發人員都在努力理解所有的數組函數,並給了我一個很好的詳細博客文章,以涵蓋所有PHP數組函數。你有興趣貢獻這樣的博客文章嗎? – JasonDavis

+0

你應該添加'array_reduce' – jcuenod

3

array_filter返回函數返回true的原始數組的元素。

array_map返回在原始數組的所有元素上調用函數的結果數組。

我不能想到你可以使用一個而不是另一個的情況。

0
  • array_map沒有副作用,而array_map從不改變它的參數。
  • array_map/array_walk的結果數組與參數具有相同數量的 元素;根據過濾函數,array_filter僅挑選數組的 元素的子集。它確實保存了密鑰。

實施例:

<pre> 
<?php 

$origarray1 = array(2.4, 2.6, 3.5); 
$origarray2 = array(2.4, 2.6, 3.5); 

print_r(array_map('floor', $origarray1)); // $origarray1 stays the same 

// changes $origarray2 
array_walk($origarray2, function (&$v, $k) { $v = floor($v); }); 
print_r($origarray2); 

// this is a more proper use of array_walk 
array_walk($origarray1, function ($v, $k) { echo "$k => $v", "\n"; }); 

// array_map accepts several arrays 
print_r(
    array_map(function ($a, $b) { return $a * $b; }, $origarray1, $origarray2) 
); 

// select only elements that are > 2.5 
print_r(
    array_filter($origarray1, function ($a) { return $a > 2.5; }) 
); 

?> 
</pre> 

結果:

Array 
(
    [0] => 2 
    [1] => 2 
    [2] => 3 
) 
Array 
(
    [0] => 2 
    [1] => 2 
    [2] => 3 
) 
0 => 2.4 
1 => 2.6 
2 => 3.5 
Array 
(
    [0] => 4.8 
    [1] => 5.2 
    [2] => 10.5 
) 
Array 
(
    [1] => 2.6 
    [2] => 3.5 
) 
1

array_map返回一個包含數組中的所有元素應用回調函數,以各一個的數組。

例如:

$a=array("a","bb","ccd","fdjkfgf"); 
$b = array_map("strlen",$a); 
print_r($b); 

//output 
Array 
(
    [0] => 1 //like strlen(a) 
    [1] => 2 //like strlen(bb) 
    [2] => 3 //like strlen(ccd) 
    [3] => 7 //like strlen(fdjkfgf) 
) 

array_filter返回只有那些陣列的元件的量,功能是真實的

例如:刪除 「BB」 從數組值

function test_filter($b) 
    { 
    if($b=="bb") 
     { 
      return false; 
     } 
    else 
     { 
      return true; 
     } 
    } 
$a=array("a","bb","ccd","fdjkfgf"); 
$b = array_filter($a,"test_filter"); 
print_r($b); 

//output 
Array 
(
    [0] => a  //test_filter() return true 
    [2] => ccd //test_filter() return true 
    [3] => fdjkfgf //test_filter() return true 
) 
1

array_filter也沒有可調用(函數)的作品被傳遞,而array_map則是必需的。

例如

$v = [true, false, true, true, false]; 
$x = array_filter($v); 

var_dump($x); 
array(3) { [0]=> bool(true) [2]=> bool(true) [3]=> bool(true) } 

array_walk改變通過在實際的陣列,而array_filterarray_map返回新的陣列,這是因爲該陣列被通過引用傳遞。