Zabawy ze wskaźnikiem tablicowym

Każda tablica posiada swój wewnętrzny wskaźnik, który, jak nietrudno się domyślić, wskazuje na „bieżący” element będący obiektem aktualnej iteracji. PHP wyposaża programistę w szereg funkcji pozwalających sprawnie operować tymże wskaźnikiem. Są to: reset(), current(), end(), prev(), next(), key() oraz each(). Do tego dochodzi jeszcze specjalny rodzaj pętli, ułatwiający iterowanie po tablicach: foreach().
current()
mixed current (array &$array)
Funkcja ta zwraca element, na który aktualnie wskazuje wewnętrzny wskaźnik tablicowy. Nie przesuwa wskaźnika w żadnym kierunku. Jeśli wskaźnik znajduje się za ostatnim elementem tablicy, wówczas zostanie zwrócona wartość FALSE.
prev()
mixed prev (array &$array)
Przesuwa wewnętrzny wskaźnik tablicy o jeden element do tyłu, a następnie zwraca wartość elementu. Zwróci FALSE jeśli tablica jest pusta, lub jeśli przed przesunięciem wskaźnik znajdował się na pierwszym elemencie tablicy.
next()
mixed next (array &$array)
Przesuwa wewnętrzny wskaźnik tablicy o jeden element do przodu, a następnie zwraca wartość elementu. Jeśli przed przesunięciem wskaźnik znajdował się na końcu tablicy, poza ostatnim elementem, lub jeśli tablica jest pusta, zostanie zwrócona wartość FALSE.
end()
mixed end (array &$array)
Przesuwa wewnętrzny wskaźnik tablicowy na ostatni element, a następnie zwraca wartość tego elementu. Zwraca FALSE w przypadku pustej tablicy.
reset()
mixed reset (array &$array)
Przesuwa wskaźnik tablicowy na pierwszy element w tablicy i zwraca jego wartość. No i jak zwykle FALSE jeśli tablica jest pusta.
key()
mixed key (array &$array)
Zwraca wartość bieżącego klucza. Jeżeli wskaźnik wewnętrzny pokazuje poza tablicę, lub tablica jest pusta, funkcja zwraca wartość NULL
each()
array each (&$array)
Funkcja ta zwraca parę klucz-wartość elementu, na który aktualnie wskazuje wskaźnik, po czym przesuwa ten wskaźnik o jeden element dalej, lub, jeśli zwrócona została para ostatniego elementu, przesuwa wskaźnik za ostatni element tablicy. Aby przywrócić wskaźnik do pozycji początkowej, należy użyć funckji reset(). Zwracana tablica ma cztery elementy o następujących indeksach: 0, 1, ‘key’, ‘value’, przy czym elementy o indeksach 0 i ‘key’ zawierają klucz, a elementy o indeksach 1 i ‘value’ zawierają wartość. Jeżeli wewnętrzny wskaźnik pokazuje za ostatni element tablicy, zwracana jest wartość NULL. Przykład funkcji wykorzystującej kilka z powyższych:
$array = array('foo' => 'bar', 'baz', 'bat' => 2);
 
function displayArray(&$array)
{
	reset($array);
	while(key($array) !== null)
	{
		echo key($array) . ": " . current($array) . '<br>';
		next($array);
	}
}
Na początku wywoływana jest reset() aby przewinąć wskaźnik na początek tablicy. Następnie używając pętli while wyświetlamy elementy tablicy w formacie „klucz: wartość„. Zauważ w jaki sposób sprawdzamy czy pętla powinna kontynuować swoje działanie. Konieczne jest absolutne porównanie za pomocą operatora !==. Dlaczego? Wyobraź sobie, że jednym z kluczy jest wartość 0. Porównując w ten sposób: 0 != null otrzymamy false i pętla się zakończy, czego wcale byśmy nie chcieli. Dlatego należy pamiętać, że przy porównywaniu wartości zwracanych przez key() (ale także przez next(), prev(), end() i current() ) musimy podwoić naszą czujność!

Prostszy sposób

Jak widać wyżej, iterowanie po tablicach za pomocą wymienionych funkcji wymaga trochę pracy. W PHP istnieje jednak specjalna pęta przeznaczona specjalnie do pracy z tablicami – foreach():
$array = array('foo', 'bar', 'baz');
 
foreach($array as $key => $value)
{
	echo $key . ': ' . $value . '<br/>';
}
Pętla ta „przelatuje” po wszystkich elementach tablicy i wyświetla je w formacie „klucz: wartość„. Należy przy tam pamiętać, że foreach() pracuje na kopii tablicy, przez co wszelkie zmiany dokonane wewnątrz pętli, nie będą miały wpływu na oryginalną tablicę. Kolejna rzecz to fakt, że foreach() zawsze przewija wskaźnik na początek tablicy toteż nie mamy wpływu na to, od którego elementu ma zacząć się iteracja. W PHP5 została wprowadzona możliwość przypisywania wartości tablicy do iterowanej zmiennej przez referencję:
$array = array(1,2,3);
 
foreach($array as &$value)
{
	$value++;
}
 
print_r($array); // tablica $array będzie zawierać teraz elementy: 2,3,4
Technika ta jest przydatna w wielu sytuacjach, jednak należy uważać na pewną pułapkę związaną z naturą przypisywania do zmiennych przez referencję. Spójrz na poniższy kod:
$array = array(1,2,3);
 
foreach($array as &$v);
foreach($array as $v);
 
print_r($array);
Jak myślisz, co będzie teraz zawierać tablica $array? Wydawało by się, że powinna nadal zwierać elementy: 1, 2 i 3, bo przecież tak naprawdę ‘przelecieliśmy’ ją tylko dwa razy pętlą foreach() ale niczego nie zmienialiśmy. Rzeczywistość jest jednak brutalna i po wywołaniu print_r($array) ujrzymy: Array ( [0] => 1 [1] => 2 [2] => 2 ) Spójrzmy dlaczego tak jest. Pierwszy foreach() faktycznie nic nie zmienia w naszej tablicy, jedynie przypisuje przez referencję po kolei każdą jej wartość do zmiennej $v. I teraz uwaga. Po zakończeniu działania pierwszej pętli, do zmiennej $v przypisany jest przez referencję ostatni element tablicy, czyli $array[2]. Jeżeli wiemy jak działają referencje, już powinniśmy wiedzieć skąd wzięła się ostateczna postać tablicy $array. Podczas drugiej iteracji do zmiennej $v ponownie przypisywane są kolejno wartości tablicy $array. Tylko że $v jest już referencją do $array[2] dlatego wszystko to, co przypiszemy do $v, przypisujemy też do ostatniego elementu tablicy. Tak wiec po pierwszej iteracji $array[2] jest równe 1, po drugiej $array[2] równa się 2, natomiast po trzeciej jest nadpisywany samym sobą więc również równa się 2. Mając to na uwadze, powinniśmy zawsze zwalniać zmienne za pomocą unset() jeśli wcześniej były one referencją.

, ,

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="">