Porównywanie tablic by ustalić wyjątkowe i unikalne elementy pierwszej tablicy, których nie ma w kolejnych tablicach.
array_diff (array tabela1, array tabela2 [, array ...])
Zwraca tablicę zawierającą wszystkie wartości tablicy tabela1, które nie są obecne w innych tablicach-argumentach. Zachowywane są przy tym klucze.
Mając dwie tablice, np.: A := {a1, ..., an} oraz B:= {a1, b1, ... , bm}
=> array_diff(A,B) = {a2, ..., an}
co oznacza, że
array_diff(A,B) zwróci nam wszystkie elementy tablicy A, które nie występują w tablicy B.
<?php $tablica1 = array ("a" => "zielony", "czerwony", "niebieski", "czerwony"); $tablica2 = array ("b" => "zielony", "żółty", "czerwony"); $wynik = array_diff ($tablica1, $tablica2); print_r($wynik); ?>
Array ( [1] => niebieski )
Dwa elementy tablicy uważane są za identyczne wtedy i tylko wtedy jeśli
(string) $element1 === (string) $element2.
Słownie: kiedy reprezentacje elementów w postaci stringów są identyczne.
Czasami przydają się jako wynik porównania tablic elementy występujące w nich kolejno jako unikalne:
$tablica1 = array ("a" => "zielony", "czerwony", "niebieski", "czerwony", "fioletowy"); $tablica2 = array ("b" => "zielony", "żółty", "czerwony"); function arrayDiff($A, $B) { $intersect = array_intersect($A, $B); return array_merge(array_diff($A, $intersect), array_diff($B, $intersect)); } print_r(arrayDiff($tablica1, $tablica2));
Array ( [0] => niebieski [1] => fioletowy [2] => żółty )
Wynikiem jest unikalny element pierwszej tablicy niebieski, fioletowy, oraz żółty w drugiej tablicy.
Funkcję tę możemy wykorzystać nieoczekiwanie do skasowania elementu tylko drugiej tablicy:
$tablica1 = array ("a" => "zielony", "czerwony", "niebieski", "czerwony", "fioletowy"); $tablica2 = array ("b" => "zielony", "żółty", "czerwony"); //pass value you wish to delete and the array to delete from function array_delete( $value, $array) { $array = array_diff( $array, array($value) ); return $array; } print_r(array_delete("zielony", $tablica2));
Array ( [0] => żółty [1] => czerwony )
Rekursywnie:
$tablica1 = array ("zielony", "czerwony", "niebieski", "czerwony", "fioletowy"); $tablica2 = array ("zielony"); function arrayRecursiveDiff($aArray1, $aArray2) { $aReturn = array(); foreach ($aArray1 as $mKey => $mValue) { if (array_key_exists($mKey, $aArray2)) { if (is_array($mValue)) { $aRecursiveDiff = arrayRecursiveDiff($mValue, $aArray2[$mKey]); if (count($aRecursiveDiff)) { $aReturn[$mKey] = $aRecursiveDiff; } } else { if ($mValue != $aArray2[$mKey]) { $aReturn[$mKey] = $mValue; } } } else { $aReturn[$mKey] = $mValue; } } return $aReturn; } print_r(arrayRecursiveDiff($tablica1, $tablica2));
Wyeliminowaliśmy kolor zielony podany z tablicy2, zostaje:
Array ( [1] => czerwony [2] => niebieski [3] => czerwony [4] => fioletowy )
Uwaga. Podobne działanie do array_diff możemy uzyskać przy pomocy kilka razy szybszej funkcji:
$tablica1 = array ("zielony", "czerwony", "niebieski", "czerwony", "fioletowy"); $tablica2 = array ("zielony", "żółty", "czerwony"); function my_array_diff($arrayFrom, $arrayAgainst) { $arrayAgainst = array_flip($arrayAgainst); foreach ($arrayFrom as $key => $value) { if(isset($arrayAgainst[$value])) { unset($arrayFrom[$key]); } } return $arrayFrom; } print_r(my_array_diff($tablica1, $tablica2));
Array ( [2] => niebieski [4] => fioletowy )
Czas pomiaru różnic czasowych w wykonaniu tych funkcji, oryginalnej i napisanej, możemy uzyskać i sobie porównać:
echo '<br>'; $t = microtime(true); $a = range(0,25000); $b = range(15000,500000); $c = array_diff($a, $b); echo microtime(true) - $t; echo '<br>'; $t = microtime(true); $a = range(0,25000); $b = range(15000,500000); $c = my_array_diff($a, $b); echo microtime(true) - $t; echo '<br>';
Czasami zachodzi potrzeba, by tablica wynikowa miała klucze zaczynające się od początku i kolejno tylko dla wszystkich elementów wynikowych nowej tablicy z porównania dwóch:
$tablica4 = array ("a" => "zielony", "czerwony", "niebieski", "czerwony", "fioletowy"); $tablica5 = array ("b" => "zielony", "żółty", "czerwony"); function array_diff_from_zero($array1, $array2){ # This wrapper for array_diff rekeys the array returned $valid_array = array_diff($array1,$array2); # reinstantiate $array1 variable $array1 = array(); # loop through the validated array and move elements to $array1 # this is necessary because the array_diff function returns arrays that retain their original keys foreach ($valid_array as $valid){ $array1[] = $valid; } return $array1; } print_r(array_diff_from_zero($tablica4, $tablica5)); echo '<br>';
Array ( [0] => niebieski [1] => fioletowy )
Czasami mamy tablicę2 wzorca o tych samych kluczach, jakie mogą pojawić się w tablicy1 badanej. Kolejna funkcja wyeliminuje elementy tablicy1 której klucze wystąpią w tablicy2 wzorca.
$tablica1 = array ("zielony", "czerwony", "niebieski", "czarny", "fioletowy"); $tablica2 = array ("zielony", "żółty", "czerwony"); $c = array_key_diff ($tablica1, $tablica2); print_r($c); function array_key_diff($ar1, $ar2) { // , $ar3, $ar4, ... // returns copy of array $ar1 with those entries removed // whose keys appear as keys in any of the other function args $aSubtrahends = array_slice(func_get_args(),1); foreach ($ar1 as $key => $val) foreach ($aSubtrahends as $aSubtrahend) if (array_key_exists($key, $aSubtrahend)) unset ($ar1[$key]); return $ar1; }
Array ( [3] => czarny [4] => fioletowy )
Weźmy następujące tablice:
$tablica1 = array ("zielony", "czerwony", "niebieski", "czarny", "fioletowy"); $tablica2 = array ("zielony", "żółty", "czerwony"); $tablica4 = array ("a" => "zielony", "czerwony", "niebieski", "czerwony", "fioletowy"); $tablica5 = array ("b" => "zielony", "żółty", "czerwony"); // returns a two dimensions array with the deleted data // and the added data function array_diff_both($new,$old) { $del=array_diff_assoc($old,$new); $add=array_diff_assoc($new,$old); return $diff=array("del"=>$del, "add"=>$add); } // returns a two dimensions array with the equal data, // deleted data and the added data function array_diff_all($arr_new,$arr_old) { $arr_equ=array_intersect_assoc($arr_new,$arr_old); $arr_del=array_diff_assoc($arr_old,$arr_new); $arr_add=array_diff_assoc($arr_new,$arr_old); return $diff=array("equ"=>$arr_equ, "del"=>$arr_del, "add"=>$arr_add); } $c = array_diff_both ($tablica1, $tablica2); print_r($c); echo '<br>'; $c = array_diff_all ($tablica1, $tablica2); print_r($c); echo '<br>';
Otrzymamy efektem porównania:
Array ( [del] => Array ( [1] => żółty [2] => czerwony ) [add] => Array ( [1] => czerwony [2] => niebieski [3] => czarny [4] => fioletowy ) ) Array ( [equ] => Array ( [0] => zielony ) [del] => Array ( [1] => żółty [2] => czerwony ) [add] => Array ( [1] => czerwony [2] => niebieski [3] => czarny [4] => fioletowy ) )
Dla innego wywołania:
$c = array_diff_both ($tablica4, $tablica5); print_r($c); echo '<br>'; $c = array_diff_all ($tablica4, $tablica5); print_r($c); echo '<br>';
Array ( [del] => Array ( [b] => zielony [0] => żółty [1] => czerwony ) [add] => Array ( [a] => zielony [0] => czerwony [1] => niebieski [2] => czerwony [3] => fioletowy ) ) Array ( [equ] => Array ( ) [del] => Array ( [b] => zielony [0] => żółty [1] => czerwony ) [add] => Array ( [a] => zielony [0] => czerwony [1] => niebieski [2] => czerwony [3] => fioletowy ) )