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);
Wyświetli on:

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

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);
A oto wynik jego działania:

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);
W wyniku zobaczymy:

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);
da taki sam wynik co poprzedni.

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 :) A to dlatego, że array_intersect_key zwraca tablicę będącą częścią wspólną WSZYSTKICH podanych do niej argumentów. Innymi słowy, porównywane klucze muszą znajdować się zarówno w pierwszej, drugiej i trzeciej tablicy. Czyli kod taki jak poniższy:
$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);
wyświetli taki rezultat:

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);
Da on w wyniku:

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);
da w wyniku:

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);
W wyniku dostajemy:

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? :)

, ,

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

*

Możesz użyć następujących tagów oraz atrybutów HTML-a: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">