2013-10-31 2 views
10

Ho esaminato gli argomenti simili nel web e l'overflow dello stack, ma ho potuto ottenere questo nella mia mente chiaramente. Difference between array_map, array_walk and array_filterDifferenza tra array_filter() e 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; 
})); 

?> 

Il codice di sopra di me restituisce una matrice filtrato il cui valore è > 2,5. Posso ottenere ciò che fa array_filter con un array_map?.

+0

Hai letto la documentazione? – sectus

risposta

16

Tutti e tre, array_filter, array_map e array_walk, utilizzare una funzione callback per scorrere una matrice molto nello stesso modo foreach loop passare attraverso un $array utilizzando $key =>$value coppie.
Per la durata di questo post, farò riferimento alla matrice originale, passata alle funzioni sopra menzionate, come $array, l'indice, della voce corrente nel ciclo, come $key e il valore della voce corrente nel ciclo, come $value.

array_filter è paragonato a query SELECT di MySQL, che seleziona i record, ma non li modifica.
Il callback dell'array_filter è passato allo $value dell'elemento del loop corrente e qualunque sia il ritorno del callback viene trattato come un booleano.
Se true, l'articolo è incluso nei risultati.
Se false, l'elemento è escluso dai risultati.
Così si potrebbe fare:

<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 d'altra parte accetta più array come argomenti. Se viene specificato un array, il valore $ dell'elemento corrente nel loop viene inviato al callback. Se si utilizzano due o più array, tutti gli array devono prima essere passato attraverso array_values ​​come indicato nella documentation:

Se l'argomento array contiene tasti stringa quindi la matrice restituita conterrà chiavi stringa se e solo se viene passato esattamente un array. Se più di un argomento viene passato quindi la matrice restituita è sempre chiavi intere

Il primo array è collegata in cascata e il suo valore viene passato al callback come primo parametro, e se un secondo array è specificato esso verrà inoltre eseguito il ciclo e il suo valore verrà inviato come secondo parametro alla richiamata e così via e così via per ogni parametro aggiuntivo.
Se la lunghezza degli array non corrispondono, il più grande matrice viene utilizzata, come menzionato nella documentation:

solito quando si usano due o più array, dovrebbero essere di uguale lunghezza perché la funzione di richiamata viene applicato in parallelo agli elementi corrispondenti . Se gli array sono di lunghezza disuguale, quelli più corti verranno estesi con elementi vuoti per corrispondere alla lunghezza dello più lunga.

Ogni volta che il callback viene chiamata, il valore restituito viene raccolto. Le chiavi vengono mantenute solo quando si lavora con un array e array_map restituisce l'array risultante. Se si lavora con due o più matrici, le chiavi vengono perse e viene invece restituito un nuovo array popolato con i risultati della richiamata. array_map invia solo al callback il valore $ dell'articolo corrente e non la sua chiave $. Se è necessaria anche la chiave, è possibile passare array_keys($array) come argomento aggiuntivo, quindi il callback riceverà sia la chiave $ che il valore $.
Tuttavia, quando si utilizzano più matrici, le chiavi originali andranno perse più o meno nello stesso modo in cui array_values ​​scarta le chiavi. Se è necessario conservare le chiavi, è possibile utilizzare array_keys per prelevare le chiavi dall'array originale e array_values per prelevare i valori dal risultato di array_map o semplicemente utilizzare direttamente il risultato di array_map poiché sta già restituendo i valori, quindi combina i due utilizzando array_combine.

Così si potrebbe fare:

<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 è molto simile a foreach($array as $key=>$value) in quanto la richiamata viene inviato sia una chiave e un valore. Accetta anche un argomento facoltativo se si desidera passare un terzo argomento direttamente al callback.
array_walk restituisce un valore booleano che indica se il ciclo è stato completato correttamente.
(Non ho ancora trovato un utilizzo pratico)
Si noti che array_walk non utilizza il ritorno del callback. Poiché array_walk restituisce un valore booleano, in modo che array_walk abbia effetto su qualcosa, è necessario fare riferimento al valore di & $ in modo da disporre di ciò che deve modificare o utilizzare un array globale. In alternativa, se non si desidera inquinare l'ambito globale, il terzo argomento facoltativo di array_walk può essere utilizzato per passare un riferimento a una variabile con cui scrivere.

Così si potrebbe fare:

<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

davvero grandi spiegazioni. L'analogia array_filter con la query SQL mi ha davvero reso chiaro grazie. Nei miei 10 o più anni con PHP ho usato raramente alcune delle funzioni di array incorporate, quindi ora mi prendo il tempo di esplorarle tutte in modo che questi esempi siano belli. Penso davvero che molti sviluppatori PHP abbiano difficoltà a comprendere tutte le funzioni dell'array e mi danno l'idea di un buon post sul blog dettagliato che copra tutte le funzioni dell'array PHP. Sareste interessati a contribuire a questo articolo del blog? – JasonDavis

+0

dovresti aggiungere 'array_reduce' – jcuenod

3

array_filter restituisce gli elementi dell'array originale per cui la funzione restituisce true.

array_map restituisce un array dei risultati della chiamata della funzione su tutti gli elementi dell'array originale.

Non riesco a pensare a una situazione in cui è possibile utilizzare l'una anziché l'altra.

0
  • array_map non ha effetti collaterali mentre array_map non modifica mai i suoi argomenti.
  • La matrice risultante di array_map/array_walk ha lo stesso numero di elementi come argomento (i); array_filter seleziona solo un sottoinsieme degli elementi dell'array in base a una funzione di filtro. Lo fa conserva le chiavi.

Esempio:

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

risultati:

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 Restituisce un array contenente tutti gli elementi di matrice dopo l'applicazione della funzione di callback a ciascuno.

ad esempio:

$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) 
) 

mentre array_filter ritorno solo gli elementi di matrice per cui la funzione è vero

esempio: rimuovere valore "BB" di matrice

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 anche funziona senza una funzione chiamabile (funzione), mentre per array_map è obbligatorio.

ad es.

$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 cambia l'array effettivo passato a, mentre array_filter e array_map ritorno nuovi array, questo è perché la matrice viene passata per riferimento.