Tablice jako stosty, kolejki lub zbiory #2
We wcześniejszym wpisie skupiłem się na zastosowaniu tablic do odwzorowania stosów i kolejek. Do tego opisałem już wstępnie za pomocą jakich funkcji możemy ułatwić sobie życie traktując tablice jako zbiory. Przede wszystkim jest to funkcja array_diff oraz wszystkie jej pochodne. W tym wpisie chciałbym skupić się na kolejnej funkcji, mianowicie na array_intersect wyznaczającą nam część wspólną dwóch, lub więcej zbiorów.
array_intersect
array array_intersect(array $array1, array $array2 [, array $ ...])
Funkcja ta, jak już wspomniałem we wstępie oblicza część wspólną z podanych jej argumentów. Widzimy, że tutaj, podobnie jak w przypadku array_diff można podać więcej niż jedną tablicę.Rozważmy taki kod:
$array1 = array('Pitt', 'Cruise', 'Pazura', 'Nicholson', 'Pacino', 'Willis'); $array2 = array('De Niro', 'Cruise', 'Pacino', 'Stuhr', 'Garcia'); $result = array_intersect($array1, $array2); print_r($result);
Array
(
[1] => Cruise
[4] => Pacino
)
Nie ma tu większej filozofii – zarówno ‘Cruise’ jak i ‘Paciono’ występują w obydwu tablicach, więc jest to cześć wspólna obu zbiorów.
Należy tutaj pamiętać, że array_intersect jak i każda jej pochodna, przy porównywaniu bierze pod uwagę wielkość liter.
Inaczej rzecz ujmując, dwa elementy są traktowane jako równe jeśli:
(string)$elem1 === (string)$elem2
Inaczej rzecz ujmując, dwa elementy są traktowane jako równe jeśli:
(string)$elem1 === (string)$elem2
array_intersect_assoc
array array_intersect_assoc(array $array1, array $array2 [, array $ ...])
Funkcja array_intersect_assoc działa na podobnej zasadzie co poprzedniczka, tzn. wynikiem jej działania jest część wspólna z podanych tablic, jednak tutaj przy porównaniu brana jest pod uwagę również zgodność kluczy.Poniższy kod jest praktycznie taki sam jak w poprzednim przykładzie, różnie się jedynie tym, że zamiast array_intersect została użyta funkcja array_intersect_assoc:
$array1 = array('Pitt', 'Cruise', 'Pazura', 'Nicholson', 'Pacino', 'Willis'); $array2 = array('De Niro', 'Cruise', 'Pacino', 'Stuhr', 'Garcia'); $result = array_intersect_assoc($array1, $array2); print_r($result);
Array
(
[1] => Cruise
)
Jak nietrudno się domyślić, wynik różni się od poprzedniego z tego powodu, że o ile wcześniej wartości ‘Pacino’ zgadzały się zarówno w jednej, jak i w drugiej tablicy, o tyle ich klucze nie są zgodne.
array_intersect_key
array array_intersect_key(array $array1, array $array2 [, array $ ... ])
Trzecia wariacja funkcji array_intersect to array_intersect_key. Działa ona tak samo jak jej „oryginalna” wersja z tą różnicą, że nieważna jest zgodność wartości tablicy, tylko kluczy.Ponownie ten sam kod, ze zmienioną nazwą funkcji:
$array1 = array('Pitt', 'Cruise', 'Pazura', 'Nicholson', 'Pacino', 'Willis'); $array2 = array('De Niro', 'Cruise', 'Pacino', 'Stuhr', 'Garcia'); $result = array_intersect_key($array1, $array2); print_r($result);
Array
(
[0] => Pitt
[1] => Cruise
[2] => Pazura
[3] => Nicholson
[4] => Pacino
)
Jest to tak naprawdę pierwsze pięć elementów tablicy $array1. Dlaczego? Jak już powiedziałem, array_intersect_key przy porównaniu bierze pod uwagę zgodność kluczy zarówno pierwszej jak i drugiej tablicy i na tej podstawie zwraca część wspólną. Zarówno w pierwszej, jak i drugiej tablicy występują klucze: 0, 1, 2, 3 i 4. Klucz 5 występuje tylko w pierwszej tablicy więc element do niego przypisany nie jest częścią wspólną. Trzeba też zwrócić uwagę, że wynikiem jest tablica zawierająca elementy tylko z pierwszej tablicy – druga jest jedynie do porównania.Zauważmy także, że nie na wynik nie ma wpływu kolejność kluczy w drugiej tablicy. Kod:
$array1 = array('Pitt', 'Cruise', 'Pazura', 'Nicholson', 'Pacino', 'Willis'); $array2 = array(1 => 'De Niro', 0 => 'Cruise', 2 => 'Pacino', 3 => 'Stuhr', 'Garcia'); $result = array_intersect_key($array1, $array2); print_r($result);
A co będzie jak dodamy do porównania kolejną tablicę, w której jeden z elementów będzie miał klucz 5? Czy wówczas w wynikowej tablicy pojawią się wszystkie elementy? No bo przecież w sumie w porównaniu będą brały udział wszystkie klucze: od 0 do 4 w tablicy $array2 i klucz 5 w tablicy $array3. Otóż, wynikiem będzie… pusta tablica
$array1 = array('Pitt', 'Cruise', 'Pazura', 'Nicholson', 'Pacino', 'Willis'); $array2 = array(1 => 'De Niro', 0 => 'Cruise', 2 => 'Pacino', 3 => 'Stuhr', 'Garcia'); $array3 = array(5 => 'Depp'); $result = array_intersect_key($array1, $array2, $array3); print_r($result);
Array
(
)
array_uintersect
Wcześniej wspomniałem, że funkcja array_intersect bierze przy porównaniu pod uwagę wielkość liter. A co jeśli chcielibyśmy żeby było inaczej, czyli żeby funkcja nie zwracała uwagi na to czy dana wartość jest pisana dużą, czy małą literą. Tutaj z pomocą przychodzi nam array_uintersect. Pozwala ona bowiem sprecyzować nam sposób w jaki będą porównywane wartości tablicy – mówiąc prościej, możemy sami napisać / podać funkcję porównującą.
array array_uintersect(array $array1, array $array2 [, array $ ...], callback $data_compare_func)
Poniżej przedstawiam użycie array_uintersect
$array1 = array('Pitt', 'Cruise', 'Pazura', 'Nicholson', 'Pacino', 'Willis'); $array2 = array('De Niro', 'Cruise', 'PACINO', 'Stuhr', 'Garcia'); $result1 = array_intersect($array1, $array2); $result2 = array_uintersect($array1, $array2, 'strcasecmp'); echo 'array_intersect()'; print_r($result1); echo 'array_uintersect()'; print_r($result2);
array_intersect()
Array
(
[1] => Cruise
)
array_uintersect()
Array
(
[1] => Cruise
[4] => Pacino
)
Jak widać w pierwszym przypadku, przy użyciu zwykłej array_intersect dostaliśmy w wyniku tylko jeden element, drugi, ‘Pacino’ został odrzucony, gdyż (string)'Pacino' !== (string)'PACINO'. W drugim przypadku do porównania została użyta funkcja strcasecmp, która nie rozróżnia wielkości liter, dlatego też w wyniku dostajemy zarówno ‘Cruise’ jak i ‘Pacino’.
array_uintersect_assoc
array array_uintersect_assoc(array $array1, array $array2 [, array $ ... ], callback $data_cmp_func)
Funkcja ta jest niemalże identyczna co poprzedniczka, z tą różnicą, że do porównania wchodzą również klucze. Tylko uwaga! O ile wartości są porównywane za pomocą funkcji dostarczonej przez użytkownika, o tyle klucze porównywane są za pomocą tej samej funkcji co w przypadku array_intersect_assoc.Rozważmy taki kod:
$array1 = array('a' => 'Almodovar', 'b' => 'Bridges', 'c' => 'Cooper', 'd' => 'Depp'); $array2 = array('a' => 'ALMODOVAR', 'b' => 'Bacon', 'C' => 'Cooper', 'D' => 'Daniels'); $result = array_uintersect_assoc($array1, $array2, 'strcasecmp'); print_r($result);
Array
(
[a] => Almodovar
)
Dlaczego? Dlatego, że pomimo tego, że element ‘Cooper’ przypisany jest raz do klucza ‘c’, a raz ‘C’ – jak widać funkcja strcasecmp nie „obejmuje” sprawdzania kluczy – dlatego funkcja array_uintersect_assoc uznała, że ten element nie stanowi części wspólnej.
array_unitersect_uassoc
Trzymając się przykładu z rozróżnianiem wielkości liter przy porównaniu, z pomocą przychodzi nam funkcja array_uintersect_uassoc. Pozwala ona bowiem użytkownikowi na zdefiniowanie funkcji porównującej zarówno dla wartości, jak i dla kluczy.
array array_uintersect_uassoc(array $array1, array $array2 [,$ ...], callback $data_cmp_func, callback $key_cmp_func)
Poniższy, zmodyfikowany kod, z użyciem array_uintersect_uassoc:
$array1 = array('a' => 'Almodovar', 'b' => 'Bridges', 'c' => 'Cooper', 'd' => 'Depp'); $array2 = array('a' => 'ALMODOVAR', 'b' => 'Bacon', 'C' => 'Cooper', 'D' => 'Daniels'); $result = array_uintersect_uassoc($array1, $array2, 'strcasecmp', 'strcasecmp'); print_r($result);
Array
(
[a] => Almodovar
[c] => Cooper
)
Czyli jak widać, tym razem wielkość liter nie grała roli przy porównywaniu kluczy.
array_intersect_uassoc
Kolejna bardzo podobna funkcja do omawianych dotychczas. Wylicza ona część wspólną z dodatkowym sprawdzaniem kluczy, przy czym owo sprawdzanie odbywa się na podstawie funkcji dostarczonej przez użytkownika. Sprawdzanie wartości przebiega natomiast w taki sam sposób jak w przypadku array_intersect.
array array_intersect_uassoc(array $array1, array $array2 [, array $ ...], callback $key_cmp_func)
array_intersect_ukey
array array_intersect_ukey(array $array1, array $array2 [, array $ ...], callback $key_cmp_func)
Ostatnia z rodziny array_intersect funkcja wylicza część wspólną porównując ze sobą tylko klucze, przy czym samo porównanie odbywa się za pomocą funkcji dostarczonej przez użytkownika. Rozważmy taki kod:
$array1 = array('a' => 'Almodovar', 'b' => 'Bridges', 'c' => 'Cooper', 'd' => 'Depp'); $array2 = array('a' => 'ALMODOVAR', 'b' => 'Bacon', 'C' => 'Christopherson', 'z' => 'Depp'); $result = array_intersect_ukey($array1, $array2, 'strcasecmp'); print_r($result);
Array
(
[a] => Almodovar
[b] => Bridges
[c] => Cooper
)
Jak widać funkcja nie dba o to jakie są wartości – liczą się tylko klucze. Dodatkowo zgodność kluczy sprawdzana jest za pomocą funkcji strcasecmp dlatego element: 'c' => 'Cooper' zaliczany jest do części wspólnej – w tablicy $array2 również występuje klucz ‘C’ (wielkość liter nie ma znaczenia, dzięki użyciu strcasecmp), to nic, że przypisana jest do niego inna wartość, array_intersect_ukey bierze pod uwagę tylko klucze, pamiętasz? Tablice jako stosy, kolejki lub zbiory #1 array_walk i array_walk_recursive