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