3. Tablice

Transkrypt

3. Tablice
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
3. Tablice
3.1. Budowa tablicy w języku PHP
W PHP każda tablica jest tablicą asocjacyjną, to jest składa się z pary „klucz – wartość”.
Nawet jeżeli używana jest jako zwykła tablica, znana z innych języków programowania,
to i tak jest to tablica asocjacyjna, po prostu klucze są kolejnymi liczbami całkowitymi od
0. Kluczami mogą być liczby całkowite lub łańcuchy tekstowe. W jednej tablicy można
mieszać klucze liczbowe i tekstowe. Oczywiście klucze liczbowe nie muszą przebiegać
kolejno. Para „klucz – wartość” zapisywana jest w PHP za pomocą operatora „=>”. Oto
zatem przykładowa tablica:
82 => 'iweifj', 'js7d' => 367, 'dfd' => $jakas_tablica, 73 => $obiekt;
O ile kluczem tablicy może być tylko liczba całkowita lub tekst, o tyle wartość może być
dowolnego typu (można dowolnie mieszać typy w jednej tablicy). Dzięki tej elastyczności
tablica w PHP może być używana jako zwykła tablica, mapa (tablica asocjacyjna), lista i
inne struktury. W szczególności elementem tablicy może być inna tablica, w ten sposób
w PHP implementujemy tablice wielowymiarowe.
W tablicy PHP należy odróżnić kolejność elementów, od kolejności kluczy. W klasycznej
tablicy z C element [3] zawsze występuje przed [4], w PHP element o kluczu 3 wcale nie
musi występować przed elementem o kluczu 4. Kolejność elementów w tablicy wynika z
kolejności wstawiania, może być zmieniana przez funkcje sortujące.
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
3.2. Tworzenie tablicy przez przypisanie
Tak jak każda zmienna, tablica w PHP powstaje w momencie pierwszego jej użycia.
Rozmiar tablicy jest dynamiczny, zawsze zajmuje tyle, ile istniejące elementy, nie
wymagane jest deklarowanie rozmiaru tablicy. Oto przykład stworzenia tablicy poprzez
jej użycie:
$tablica[19] = 247;
Powstaje tablica jednoelementowa zawierająca parę „19 => 247”. Nie należy myśleć, że
tworzone są również elementy o kluczach 0 – 18, tworzony jest tylko i wyłącznie jeden
element. Kolejne przypisania do tej samej tablicy dodają do niej kolejne elementy:
$tablica['hg'] = 837;
$tablica[384] = 'Politechnika';
Można przy tworzeniu elementu tablicy pominąć wartość klucza. Wtedy klucz jest liczbą o
1 większą od największego klucza liczbowego istniejącego dotychczas w tablicy. Jeżeli w
tablicy są tylko klucze tekstowe (albo nie ma żadnych elementów), klucz otrzymuje
wartość 0.
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
3.3. Tworzenie tablicy operatorem array()
Operator array() służy do stworzenia tablicy z podanych par „klucz – wartość”. Oto
podstawowy przykład jego zastosowania:
$tablica = array('fdf' => 73, 43 => 'hswi', 'deed' => 'Gsnbe');
Przy podawaniu kolejnych par można pominąć klucze. W takim przypadku klucz jest
generowany automatycznie. Klucz automatyczny jest zawsze liczbowy. Wyszukiwany jest
największy istniejący w tablicy klucz liczbowy, zwiększany jest o 1 i staje się kluczem
nowego elementu. Jeżeli dotychczas w tablicy nie było kluczy liczbowych, klucz
automatyczny startuje od 0:
$tablica = array('g' => 4, 'f', 5 => 'a', 33);
Powstaje następująca tablica:
'g'
0
5
6
=>
=>
=>
=>
4, dcfdf
'f', (wcześniej nie wystąpił żaden klucz liczbowy, więc 0)
'a', edfed
33 (największy klucz liczbowy do tej pory to 5, więc nowy to 6)
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
3.4. Operatory działające na tablicach
Niektóre operatory PHP mają specyficzne działanie w odniesieniu do tablic. Te operatory
to: „+”, „==”, „!=” (którego synonimem jest „<>”).
operator „+”
Powoduje dołączenie do tablicy stojącej po lewej stronie wszystkich elementów z tablicy
po prawej, których klucze nie występują po lewej. Tak więc w wypadku zduplikowanych
kluczy, pozostawiane są wartości w tablicy po lewej stronie operatora.
$a = array(6 => 3, 8 => 2, 12 => 7);
$b = array(3 => 4, 6 => 7);
$a + $b daje w wyniku (6 => 3, 8 => 2, 12 => 7, 3 => 4)
Proszę zwrócić uwagę na niezmienioną kolejność elementów, elementy z tablicy po
prawej są zawsze dodawane na końcu.
operatory „==” i „!=”
Służą do porównywania zawartości tablic, „==” jest prawdziwy, jeżeli obie tablice
zawierają te same pary klucz – wartość. Drugi jest przeciwieństwem pierwszego.
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
3.5. Tablica traktowana jako lista
Elementy tablicy (pary klucz – wartość) są uporządkowane w pewnej kolejności, która
wynika z kolejności wstawiania elementów do tablicy (każdy nowy element jest
wstawiany na koniec). Każda tablica posiada tak zwany wskaźnik, który wskazuje na
jeden z elementów i może być przesuwany za pomocą zestawu funkcji. W ten sposób
można używać tablicy jako listy.
current()
next()
prev()
end()
key()
reset()
–
–
–
–
–
–
zwraca wartość elementu wskazywanego przez wskaźnik,
przesuwa wskaźnik o jeden element do przodu i zwraca wartość elementu,
przesuwa wskaźnik o jeden element do tyłu i zwraca wartość elementu,
przesuwa wskaźnik na koniec tablicy i zwraca wartość ostatniego elementu,
zwraca klucz elementu wskazywanego przez wskaźnik,
ustawia wskaźnik na początek tablicy i nic nie zwraca.
$a = array('f'=>6, 56=>'d', 'g'=>'xx', 44=>16);
$x = current($a);
// 6
$x = next($a);
// 'd'
$x = end($a);
// 16
$x = key($a);
// 44
$x = prev($a);
// 'xx'
reset($x);
$x = prev($a);
// FALSE
$x = end($a);
// 16
$x = next($a);
// FALSE
$x = key($a);
// FALSE
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
Tablica traktowana jako lista (c.d.)
Przy używaniu tych operatorów należy zwrócić uwagę na pewien fakt. W przypadku
wyjścia poza tablicę prev() i next() mogą zwrócić FALSE. Sytuacja ta jest nie do
odróżnienia od przypadku, kiedy w tablicy znajduje się element typu logicznego o
wartości FALSE. Przypadki te odróżnić można za pomocą key(), ponieważ przy
ustawieniu wskaźnika poza tablicą key() zwróci wartość typu NULL, a klucz tablicy nie
może być typu NULL. Niemniej przy zwykłym porównaniu wartość NULL może zostać
niejawnie przekształcona do łańcucha pustego albo liczby 0. Dlatego należy do
sprawdzania stosować operator identyczności („===”). Działa on tak samo, jak operator
porównania, ale wymaga aby porównywane zmienne były tych samych typów i nie
dokonuje domyślnych konwersji. Jeżeli typy się różnią, wynikiem porównania jest fałsz
logiczny. Oto kilka przykładów:
0 == 0
0 === 0
0 == NULL
0 === NULL
'0' == 0
'0' === 0
'' == NULL
'' === NULL
//
//
//
//
//
//
//
//
prawda
prawda
prawda
fałsz
prawda
fałsz
prawda
fałsz
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
3.6. Konstrukcja each()
Operator each() służy do pobierania z tablicy kolejnych elementów. Inaczej niż
poprzednio omówione, pobiera z tablicy cały element (klucz i wartość) umieszczając je w
specyficznej, czteroelementowej tablicy wyglądającej następująco:
0
'key'
1
'value'
=>
=>
=>
=>
(klucz elementu)
(klucz elementu)
(wartość elementu)
(wartość elementu)
Jak widać do klucza i wartości zwróconego elementu możemy się odwoływać zarówno
poprzez indeksy liczbowe, jak i poprzez klucze opisowe. Operator each() przesuwa po
pobraniu elementu wskaźnik tablicy na następny element. Oto przykład emitujący tablicę
PHP jako dwukolumnową tabelę w HTML:
<table border="1"><tr><th>klucz</th><th>wartosc</th></tr><?
while ($e = each($tablica))
{
print("<tr><td>{$e['key']}</td><td>{$e['value']}</td></tr>");
}
</table>
Operator each() po wyjściu poza ostatni element tablicy zwraca FALSE.
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
3.7. Konstrukcja foreach()
Ta konstrukcja również służy do przemieszczania się po tablicy, robi to jednak w inny
sposób. Po pierwsze foreach() samo w sobie konstruuje pętlę przebiegającą po
elementach tablicy, nie ma potrzeby samodzielnego organizowania tej pętli przez while
czy for. Po drugie konstrukcja ta automatycznie ustawia wskaźnik tablicy na początku.
Po trzecie foreach() pracuje na lokalnej kopii tablicy, co ma swoje zalety, ale też i
wady. Ponieważ PHP bardzo często pracuje na dużych tablicach (np. ładowanych z
relacyjnych baz danych), nieprzemyślane użycie foreach() może się okazać bardzo
kosztowne. Kopiowania tablicy można uniknąć podając funkcji referencję do oryginału. W
czasie wykonywania kolejnych iteracji pętli przesuwany jest zarówno wskaźnik kopii
roboczej, jak i wskaźnik oryginalnej tablicy. Oto składnia:
foreach($tablica as $wartość)
{
// $wartość zawiera wartości kolejnych elementów
}
albo
foreach($tablica as $klucz => $wartość)
{
// $klucz zawiera klucze, a $wartość wartości kolejnych elementów
}
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
Konstrukcja foreach() (c.d)
Dla porównania z each() i samodzielnie konstruowaną pętlą, tym razem przykład
wyświetlający tablicę PHP jako tabelę HTML przy użyciu foreach():
<table border="1"><tr><th>klucz</th><th>wartosc</th></tr><?
foreach($tablica as $klucz => $wartosc)
{
print("<tr><td>$klucz</td><td>$wartosc</td></tr>");
}
</table>
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
3.8. Sortowanie tablic
Rozpatrywanie zagadnienia sortowania wymaga rozpatrzenia w jaki sposób PHP
porównuje ze sobą elementy różnych typów. Operacja porównania dwóch elementów
sortowanej tablicy jest podstawą każdego algorytmu sortowania. W klasycznych językach
z silną typizacją tablica po prostu zawsze składa się z elementów tego samego typu i
problem porównania dwóch elementów zwykle nie nastręcza problemów. W PHP tablica
może zawierać wartości różnych typów i przy ich porównywaniu możemy się natknąć na
różne niespodzianki. Oto kilka typowych zagwozdek:
●
przy porównaniu liczby z tekstem, tekst jest zamieniany na liczbę,
●
przy porównaniu dwóch tekstów reprezentujących liczby, są one zamieniane na
liczby,
●
porównywanie ze sobą dziwnych rzeczy w rodzaju tablice, zasoby, czy obiekty, nie
jest generalnie zalecane, jeżeli ktoś się jednak uprze powinien poczytać dokumentację
a potem przetestować efekty na tej wersji PHP, na której będzie docelowo pracował
skrypt (mogą być np. różnice między PHP 4 i 5).
PHP posiada nadspodziewanie wiele funkcji do sortowania tablic. Fakt ten wynika, że
każdy element tablicy jest parą klucz – wartość, a to stwarza wiele możliwości
sortowania. Zacznijmy od najprostszych metod.
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
Sortowanie tablic (c.d.)
3.8.1. Sortowanie tradycyjne – sort() i rsort()
To sortowanie opiera się wyłącznie na wartościach elementów, całkowicie ignorując
klucze. Elementy zostają poprzestawiane według narastających (lub malejących dla
rsort()) wartości, stare klucze zostają usunięte, następnie zostają stworzone nowe klucze
liczbowe od 0 zwiększające się o 1 przy każdym elemencie.
$tablica
sort($tablica)
rsort($tablica)
klucz
wartość
klucz
wartość
klucz
wartość
28
-177
0
-177
0
92
71
'jabłko'
1
'jabłko'
1
'pisak'
19
'pisak'
2
'pisak'
2
'jabłko'
36
92
3
92
3
-177
W tym przypadku sortowanie odbywa się w ten sposób, że łańcuch tekstowy przy
porównywaniu z liczbą jest konwertowany na liczbę, co przy łańcuchach nie będących
reprezentacją liczb zmienia je na 0. Przy porównaniu dwóch łańcuchów natomiast stosuje
się porównywanie tekstu (litera po literze). Sposób porównywania można zmienić
podając drugi parametr funkcjom sortującym, określający sposób konwersji wartości
przed porównaniem.
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
Sortowanie tablic (c.d.)
$tablica
sort($tablica, SORT_NUMERIC) rsort($tablica, SORT_NUMERIC)
klucz
wartość
klucz
wartość
klucz
wartość
28
-177
0
-177
0
92
71
'jabłko'
1
'pisak'
1
'pisak'
19
'pisak'
2
'jabłko'
2
'jabłko'
36
92
3
92
3
-177
Tym razem wszystkie teksty są przed porównaniami konwertowane na liczby. Oczywiście
teksty nie reprezentujące liczb dają w wyniku konwersji 0 i ich wzajemna kolejność nie
jest określona.
$tablica
sort($tablica, SORT_STRING)
rsort($tablica, SORT_STRING)
klucz
wartość
klucz
wartość
klucz
wartość
28
-177
0
-177
0
'jabłko'
71
'jabłko'
1
92
1
'pisak'
19
'pisak'
2
'jabłko'
2
92
36
92
3
'pisak'
3
-177
Tym razem liczby są przed porównaniem konwertowane na łańcuchy tekstowe. Jeżeli
teksty zawierają znaki narodowe należy użyć SORT_LOCALE_STRING.
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
3.8.2. Sortowanie z pozostawieniem kluczy – asort(), arsort()
Sortowanie jest również według wartości (zatem kolejność elementów tablicy będzie taka
sama jak przy sort()), ale zostają pozostawione stare klucze elementów.
$tablica
asort($tablica)
arsort($tablica)
klucz
wartość
klucz
wartość
klucz
wartość
28
-177
28
-177
36
92
71
'jabłko'
71
'jabłko'
19
'pisak'
19
'pisak'
19
'pisak'
71
'jabłko'
36
92
36
92
28
-177
Drugi parametr, definiujący sposób porównywania wartości przy sortowaniu, ma to samo
znaczenie jak dla funkcji sort().
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
3.8.3. Sortowanie według kluczy – ksort(), krsort()
Tym razem tablica zostaje posortowana według kluczy, oczywiście przemieszczane są
całe elementy, a więc klucz z odpowiadającą mu wartością.
$tablica
ksort($tablica)
krsort($tablica)
klucz
wartość
klucz
wartość
klucz
wartość
28
-177
19
'pisak'
71
'jabłko'
71
'jabłko'
28
-177
36
92
19
'pisak'
36
92
28
-177
36
92
71
'jabłko'
19
'pisak'
Również w tym przypadku sposób sortowania kluczy można zmienić podając drugi
parametr funkcji sortującej.
Generalnie wymieszanie różnych typów wartości (dla sort(), rsort(), asort(), arsort()),
czy różnych typów kluczy (dla ksort() i krsort()) jest złym pomysłem i powinno się tego
unikać aby zapobiec problemom z nieoczekiwanymi wynikami sortowania. Jeżeli
programista decyduje się na sortowanie wymieszanych typów, powinien mieć pełną
świadomość tego co robi.
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
3.9. Usuwanie tablic i ich elementów operatorem unset()
Operator unset() służy do usuwania istniejących zmiennych. W przypadku tablic możemy
go użyć do usunięcia całej tablicy, lub też usunięcia wybranych elementów. W PHP
wszystkie zmienne są automatycznie usuwane przy zakończeniu skryptu (niektóre nawet
wcześniej). Stosowanie unset() ma sens przy dużych zmiennych (np. tablicach), które
nie są więcej potrzebne w programie. W ten sposób zmniejsza się zapotrzebowanie
skryptu na pamięć (język PHP potrafi limitować przydział pamięci dla skryptu i z reguły
to limitowanie jest włączone).
unset($tablica);
unset($tablica['h'])
// usunięcie całej tablicy
// usunięcie z tablicy elementu o kluczu 'h'
Usunięcie wszystkich elementów tablicy nie jest równoznaczne z usunięciem samej
tablicy – tablica nadal istnieje i jest pusta (zawiera 0 elementów).
3.10. Liczenie elementów tablicy
Funkcja count(), której synonimem jest sizeof(), zwraca ilość elementów znajdujących
się w tablicy.
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
3.11. Zapisywanie wartości tablicy do serii zmiennych
Operator list() pozwala na umieszczenie kolejnych elementów tablicy w podanej liście
zmiennych. Oto najprostszy przykład:
$wozy = array('audi', 'bmw', 'lancia');
list($pierwszy, $drugi, $trzeci) = $wozy;
echo $pierwszy; ?><br><?
echo $drugi; ?><br><?
echo $trzeci;
audi
bmw
lancia
Uwaga! Operator list() wstawiając wartości tablicy do zmiennych, kieruje się kluczami.
Oznacza to, że do pierwszej zmiennej zostanie wstawiona wartość elementu o kluczu 0,
do drugiej wartość elementu o kluczu 1 i tak dalej. Kolejność elementów w tablicy nie
ma żadnego znaczenia. Jeżeli chcemy pominąć jakiś klucz przy wstawianiu (bo np. nie
ma elementu z takim kluczem w tablicy) stawiamy w liście zmiennych „pusty” przecinek.
Oto przykład ilustrujący te zagadnienia.
mgr inż. Grzegorz Kraszewski – TECHNOLOGIE INTERNETOWE 3 – wykład 3: „Tablice”.
Zapisywanie wartości tablicy do serii zmiennych (c.d.)
$wozy = array(2=>'audi', 0=>'bmw', 3=>'lancia');
// kolejność
list($pierwszy, , $drugi, $trzeci) = $wozy;
echo $pierwszy; ?><br><?
echo $drugi; ?><br><?
echo $trzeci;
// „pusty” przecinek
// za brakujący element 1
bmw
audi
lancia