Dette er en utskriftsvennlig versjon

Guide: PHP- & MySQL-innføring: Kapittel 4

Lister (arrays)

Programmeringsspråket PHP har blitt svært populært de siste årene. Vi fortsetter vår innføring med å ta for oss lister.

Side 1: Introduksjon

PHP er et fullverdig programmeringsspråk og det tar derfor noe tid å dekke alt. I det første kapittelet har vi dekket grunnleggende bakgrunnsinformasjon om PHP, hva det er og brukes til.

Det andre kapittelet dekket grunnleggende syntaks, variabler, uttrykk og utskrift.

Og til slutt, i kapittel tre, gikk vi gjennom kontrollstrukturer som lar deg vise ulik informasjon til brukeren avhengig av verdien til variabler, og løkker som lar deg gjenta instruksjoner flere ganger.

Lister, gjerne også kjent som arrays, brukes til å lagre indekssortert data for hurtige oppslag. Akkurat det sier deg gjerne ikke så mye, men definisjonen er svært vag fordi den omfatter svært mye. Den enkleste måten å tenke på en array på, er som en nummerert liste. Men, på grunn av fleksibiliteten til PHP, trenger man ikke bruke tall for å nummerere lista! Forvirret?

I dette kapittelet skal vi gå gjennom de vanligste bruksområdene av arrays, og vanlige operasjoner å gjøre på dem.

Side 2: Opprette arrays

Opprette arrays

Som svært mange ting i PHP finnes det flere måter å lage arrays på. Men først og fremst; en array behandles på svært mange måter akkurat som en annen variabel i PHP. Array er rett og slett en ekstra datatype, som lar deg gjøre litt flere ting enn med vanlige variabler.

<?php
$farger 
= Array("BlÃ¥""Rød""Grønn");
print_r($farger);
?>

En av de vanligste måtene å opprette en array på er slik som over. Funksjonen Array() (vi skal snakke mer om funksjoner i neste kapittel) tar inn en rekke verdier som arrayen vil bestå av. print_r() skriver ut innholdet av en variabel på en annen måte enn echo gjør. Om du kjører dette skriptet får du ut følgende data;

Array
(
    [0] => Blå
    [1] => Rød
    [2] => Grønn
)

Den første linjen indikerer at variabelen vi skrev ut er en array. De to parentesene viser hva som er innholdet i denne arrayen. [0] beskriver indeks 0, og som inneholder verdien "Blå". Indeks 1 inneholder "Rød", og indeks 2 inneholder "Grønn". Det er verdt å merke seg at den første indeksen begynner på 0 og ikke på 1 som gjerne er mer naturlig for mennesker.

<?php
$farger 
= Array("BlÃ¥""Rød""Grønn");
$farger[0] = "Turkis";
$farger[]  = "Rosa";
print_r($farger);
?>

To små tillegg til funksjonen over viser at vi kan bytte ut fargen som er indeksert som nummer 0 ved å overskrive $farger[0]. Du kan også få tak i innholdet i indeks 0 ved å bruke samme notasjon. Vi kan også legge til en ekstra farge på slutten av arrayen ved å bruke $farger[], som automatisk legger til neste tall. I dette tilfellet ville $farger[3] vært det samme, men å bruke tomme klammer gjør at PHP selv finner ut hvilken indeks den skal sette inn. Under ser du resultatet av skriptet over.

Array
(
    [0] => Turkis
    [1] => Rød
    [2] => Grønn
    [3] => Rosa
)

Alternativ oppretting

Den alternative måten å starte arrays på, er å bare begynne å jobbe direkte med klamme-notasjonen. Arrayen ovenfor kan like lett lages ved å gjøre følgende:

<?php
$farger
[] = "BlÃ¥";
$farger[] = "Rød";
$farger[] = "Grønn";
?>

Variabelen $farger opprettes da som en array fra den blir brukt første gang. Man kunne også satt inn tallene direkte.

Side 3: Løkker og arrays

Løkker og arrays

Arrays blir svært ofte benyttet for å bla gjennom en rekke med data, og liste dem opp for nettleseren, eller å gjøre utregninger med verdiene. Det finnes flere måter å gjøre dette på, og alle involverer løkker, som vi snakket om i kapittel 3. En av de letteste å bruke når det er snakk om arrays, er foreach, som vi ikke har nevnt før.

foreach

foreach-løkker, direkte oversatt til "for hver"-løkker, blar gjennom hvert eneste element i arrayen, og lar deg gjøre operasjoner på disse elementene. Et enkelt eksempel følger;

<?php
$farger 
= Array("Rød""Grønn""BlÃ¥");
foreach (
$farger as $farge)
{
    echo 
$farge."<br/>";    
}
?>

Dette skriptet skriver ut "Rød", "Grønn" og "Blå" på hver sin linje. foreach-delen sier at man skal bruke $farger-arrayen, og kalle hvert element for $farge. Inne i løkken kan vi da skrive ut $farge, og den variabelen endrer verdi til en ny farge fra arrayen hver gang løkken gjennomgås.

Det finnes også en utvidet versjon av foreach, som lar deg få tilgang på nøkkelen for hvert element i tillegg til dataene. Da blir det seende slik ut;

<?php
$rangeringer 
= Array(=> "Gull"=> "Sølv"
    
=> "Bronsje"10 => "Taper!");
foreach (
$rangeringer as $indeks => $verdi)
{
    echo 
$indeks.". ".$verdi."<br/>";
}
?>

Legg merke til at vi her definerer indeks 1, 2, 3 og 10, og at foreach bare skriver ut disse. foreach-løkken fyller nå også inn 2 variabler, $indeks og $verdi, som blir fylt med henholdsvis indeksverdien og dataverdien for den gjennomkjøringen.

Merk at dersom du forsøker å overskrive $verdi i foreach-løkken, vil ikke $rangeringer bli påvirket av det. Det er fordi $verdi bare er en kopi av verdien, og ikke en peker til verdien i $rangeringer. Dersom du ønsker å endre arrayen $rangeringer, blir du nødt til å bruke indeksen direkte i arrayen; $rangeringer[$indeks] = "ostekake";.

for

Dersom du har en array med uavbrutt sekvensielt nummererte indekser, kan du bruke en for-løkke for å bla gjennom den. Det er ofte gjerne enklere å benytte seg av foreach, men likevel er for-løkker noe av det vanligste å se når det gjelder gjennomsøking av arrays.

<?php
$rangeringer 
= Array(=> "Gull"=> "Sølv"
    
=> "Bronsje");
for (
$i 1$i <= 3$i++)
{
    echo 
$i.". ".$rangeringer[$i]."<br/>";
}
?>

Det er svært lite spesielt med hvordan for-løkker fungerer i forbindelse med arrays, så denne kommenteres svært lite. Hva hadde forresten skjedd her om vi hadde hatt den samme $rangeringer-variabelen som i kodeeksempelet ovenfor?

Andre løkker

Det finnes selvsagt også andre måter å bla gjennom arrays på, en av dem er syntaksen hvor man bruker en while-løkke med noen spesielle array-funksjoner. Denne er funksjonelt identisk med foreach, og du kan lese om den på manualens side om foreach.

Side 4: Mer om indekser

Mer om indekser

Indeksene, gjerne også kjent som nøklene eller keys, i en array kan også være andre ting enn heltall. Til nå har vi holdt oss eksklusivt til å bruke heltall som indekser, men det er ingenting i veien for at indekser kan være tekst, men de kan ikke være flyttall eller objekter.

Dette gjør arrays i PHP svært fleksible, og arrays er optimert for flere forskjellige bruksområder. Det betyr at de uansett er svært raske å slå opp i, å sette inn verdier i og å oppdatere verdier, og dette er gjerne noe man ikke trenger å bekymre seg for i daglig bruk.

Arrays trenger ikke være sortert etter indeksene, men blir normalt sortert etter rekkefølgen ting blir satt inn i. Så, dersom du blar gjennom en array ved hjelp av foreach (mer om denne senere) vil du gjerne ofte oppleve at indeks 3 kan komme før indeks 1. Det gjør at vi gjerne må sortere arrays med jevne mellomrom.

<?php
$rangeringer 
= Array(10 => "Taper!"=> "Sølv"
    
"a" => "Gull"=> "Bronsje");
foreach (
$rangeringer as $indeks => $verdi)
{
    echo 
$indeks.". ".$verdi."<br/>";
}
?>

Koden ovenfor demonstrerer mye av dette. Her ser du at innholdet i arrayet er lagt til i rekkefølgen 10, 2, "a", 3, og foreach-løkken vil derfor skrive ut dette i den rekkefølgen. Legg også merke til at en av indeksene er en string ("a"), og at dette ikke er noe problem for PHP.

10. Taper!
2. Sølv
a. Gull
3. Bronsje

En ting som er spesielt med PHP, i alle fall i forhold til mange andre programmeringsspråk, er at arrays er assosiative. Det betyr at dersom en verdi har indeks 4, og du sletter element 0, 1, 2 og 3 i arrayen, vil fremdeles den samme verdien ligge lagret i indeks 4. Det gjør at traversering med en for-løkke kan føre til feil dersom du har slettet noe i arrayen.

Side 5: Sortering

Sortering

Det finnes en hel rekke interne funksjoner i PHP som lar deg sortere arrays på ulike måter. Disse funksjonene blir som oftest brukt før man skal gjennomgå en liste med blant annet foreach-løkker. Her er en kort beskrivelse;

sort()

Denne funksjonen sorterer en array basert på verdiene i arrayen. Indeksene blir byttet ut med heltall som starter på null. Om verdiene i arrayet er strenger, vil de ende opp i alfabetisk rekkefølge.

<?php
$rangeringer 
= Array(10 => "Taper!"=> "Sølv"
    
"a" => "Gull"=> "Bronsje");
sort($rangeringer);
print_r($rangeringer);
?>

Legg merke til at sort() endrer selve variabelen som du sender inn, og dette gjelder også de andre sorteringsfunksjonene. Resultatet av en gjennomkjøring blir i dette tilfellet (legg merke til at verdiene er alfabetisk sortert);

Array
(
    [0] => Bronsje
    [1] => Gull
    [2] => Sølv
    [3] => Taper!
)

asort()

En a i begynnelsen av funksjonsnavnet står for assosiativ. Det betyr at de originale indeksene blir beholdt, og at det bare er rekkefølgen på elementene som blir endret. Ellers sorterer asort() i samme rekkefølge som sort(). Ved å bytte ut funksjonkallet i eksempelet ovenfor med asort() vil vi få følgende resultat;

Array
(
    [3] => Bronsje
    [a] => Gull
    [2] => Sølv
    [10] => Taper!
)

rsort() og arsort()

En r i begynnelsen av funksjonsnavnet står for reversert. Det betyr at strenger blir sortert i reversert alfabetisk rekkefølge. Dette kan kombineres med assosiativ sorteringer, og dermed får vi to funksjoner rsort() og arsort(). Her er resultatet av rsort;

Array
(
    [0] => Taper!
    [1] => Sølv
    [2] => Gull
    [3] => Bronsje
)

Slik blir arsort();

Array
(
    [10] => Taper!
    [2] => Sølv
    [a] => Gull
    [3] => Bronsje
)

ksort() og krsort()

Om du vil sortere en array etter indeksene i arrayen, bruker du funksjonene som begynner på k. ksort() og krsort() sorterer nøklene alfabetisk og reversert alfabetisk, og tar selvsagt vare på indeksene.

Resultatene fra eksemplene ovenfor blir som følger, først for ksort();

Array
(
    [2] => Sølv
    [3] => Bronsje
    [10] => Taper!
    [a] => Gull
)

Legg merke til at "a" kommer etter heltallet 10. Deretter krsort();

Array
(
    [a] => Gull
    [10] => Taper!
    [3] => Bronsje
    [2] => Sølv
)

Side 6: Vanlige operasjoner

Vanlige operasjoner

Det er ofte man trenger å fjerne elementer fra en array, finne indeksen til spesifikke verdier, og lignende. PHP har en rekke innebygde funksjoner for å gjøre dette, og her presenterer vi noen av dem. I manualen finner du en rekke andre slike funksjoner, vi har kun valgt ut noen av de viktigste.

count()

count() gir deg antallet elementer i arrayet. Svært nyttig om du har en kontinuerlig sekvensielt nummerindeksert array.

<?php
$array 
= Array("Ola""Lars""Per""Nils");
for (
$i 0$i count($array); $i++)
{
    echo 
$array[$i]."<br/>\n";    
}
?>

array_reverse()

array_reverse() snur arrayet motsatt vei, slik at de første verdiene kommer til slutt. Den tar en eller to parametre, den første er arrayet som skal snus, den valgfrie nummer to angir om indeksene skal bevares. Den nye arrayen kommer ut som returverdi.

array_key_exists() og in_array()

array_key_exists() sjekker om en indeks finnes i en array, og returnerer en boolsk verdi. Den første parameteren er indeksen som den skal prøve å finne, og den andre angir arrayet.

in_array() sjekker om en verdi finnes i en array, og returnerer en boolsk verdi. Den første parameteren angir verdien som man skal prøve å finne, den andre angir arrayet det skal søkes i.

<?php
$array 
= Array("Ola""Lars""Per""Nils");
if (
array_key_exists(2$array))
    echo 
"Fant indeks 2!<br/>";
if (
in_array("Ola"$array))
    echo 
"Fant Ola!<br/>";
?>

array_rand()

array_rand() plukker et eller flere elementer tilfeldig fra et array, og returnerer enten en enkel verdi (om du plukker et element) eller en array. Verdiene du får ut er indeksene til de tilfeldige elementene, ikke verdiene. Parameter nummer to angir hvor mange elementer som skal plukkes, og om du utelater den plukkes bare et element.

<?php
$array 
= Array("Ola""Lars""Per""Nils");
// plukk ut et element
print_r(array_rand($array));
echo 
"\n";
// plukk ut tre elementer
print_r(array_rand($array3));
?>

shuffle()

shuffle() endrer rekkefølgen til verdien i arrayen, og fjerner alle indeksene. Den returnerer ingenting, men endrer på selve arrayen du sender inn.

<?php
$array 
= Array("Ola""Lars""Per""Nils");
shuffle($array);
print_r($array);
?>

Side 7: Køer og stakker

Køer og stakker

Sortering er ikke det eneste man ønsker å gjøre med arrays. Ofte vil man behandle arrays som en kø eller som en stakk. Her er hvordan det gjøres.

Array som kø

Det finnes to funksjoner som lar deg behandle en array som en kø, nemlig array_push() og array_shift(). En kø er en liste hvor du legger til verdier i en ende og fjerner i den andre enden; altså et først inn, først ut-system. En analogi finner du i hvordan du stiller deg opp i kø på dagligvarebutikken.

Selvsagt finnes det en egen terminologi for operasjoner på en kø; vi kaller det å "pushe" elementer inn i køen når vi legger til nye ting, og å "shifte" elementer fra køen når vi fjerner ting.

array_push() legger til elementer bakerst i arrayet;

<?php
$queue 
= Array("Ola""Lars");
array_push($queue"Per");
array_push($queue"Nils");
print_r($queue);
?>

Resultatet blir;

Array
(
    [0] => Ola
    [1] => Lars
    [2] => Per
    [3] => Nils
)

Observante lesere legger gjerne merke til at array_push() gjør det samme som $queue[]. For å fjerne elementer framme i arrayen bruker vi array_shift();

<?php
$queue 
= Array("Ola""Lars");
array_push($queue"Per");
array_push($queue"Nils");
$person array_shift($queue);
print_r($queue);
print_r($person);
?>

Ut fra dette skriptet får vi følgende utskrift;

Array
(
    [0] => Lars
    [1] => Per
    [2] => Nils
)
Ola

Du kan se at Ola har blitt fjernet fra køen, og blir gitt som resultat fra array_shift()-funksjonen.

Arrays som stakk

En stakk er en liste basert på først inn, sist ut-prinsippet. Tenk deg en stabel med tallerkner når du vasker opp. Du legger rene tallerkner på toppen av stabelen, mens personen som tørker også plukker fra toppen av den. Det betyr at den siste tallerkenen som blir lagt på, blir den første som blir tatt ut.

Stakker er svært mye brukt i lavnivåprogrammering på datamaskiner, men gjerne ikke like ofte i programmering på det nivået som PHP ligger på. Likevel har vi selvsagt tilgang på funksjoner for å behandle en array som en stakk; disse heter array_push() og array_pop().

I en kø snakket vi om å "pushe" verdier på slutten av køen, og å "shifte" verdier fra starten. I en stakk "pusher" vi verdier på stakken, og "popper" verdier fra stakken.

Stakker brukes veldig ofte i systemer der man regelmessig veksler mellom å lese og skrive til listen, og eksempelet nedenfor viser dette. Det er gjerne noe mer avansert enn de vi har sett på tidligere. Det er ikke noe problem å modifisere skriptet til å bruke køer istedet for stakker, da trenger du bare å bytte ut array_shift() med array_pop().

<?php
$stack 
= Array();
// La oss starte med verdiene (0, 1, 2) p� stakken
array_push($stack012);
$i 2;
// Fortsett til stakken er tom
while (count($stack) > 0)
{
    
// Halvparten av tiden legger vi til verdier
    // (Men pass samtidig p� at vi ikke f�r for mange verdier)
    
if (mt_rand(020) < 10 && count($stack) < 10)
    {
        
$i++;
        
array_push($stack$i);
        
// lag oversikt over stakken
        
$str implode(", "$stack);
        echo 
"+ Pushet $i \tStakk: ($str)\n";
    }    
    else
    {
        
$verdi array_pop($stack);
        
// lag oversikt over stakken
        
$str implode(", "$stack);
        echo 
"- Shiftet $verdi \tStakk: ($str)\n";
    }
}
?>

count() i koden ovenfor brukes for å finne lengden på en hvilken som helst array. mt_rand() er en funksjon som gir tilbake et tilfeldig tall, i dette tilfellet mellom 0 og 20, og vi sjekker om dette tallet er mindre enn 10. implode()-funksjonen slår sammen en array til en string, og bruker en streng vi oppgir (i dette tilfellet komma og et mellomrom) mellom verdiene.

Resultatet fra dette skriptet blir forskjellig hver gang, men under finner du typisk utdata fra skriptet. Linjer som begynner med pluss betyr at en verdi ble lagt til på stakken, linjer som begynner med minus indikerer at en verdi ble fjernet. På slutten av hver linje finner man også det nåværende innholdet på stakken. Som dere ser begynner vi med en stakk som inneholder (0, 1, 2) for at skriptet ikke skal avslutte med en gang.

- Shiftet 2 	Stakk: (0, 1)
- Shiftet 1 	Stakk: (0)
+ Pushet 3 	Stakk: (0, 3)
+ Pushet 4 	Stakk: (0, 3, 4)
- Shiftet 4 	Stakk: (0, 3)
- Shiftet 3 	Stakk: (0)
+ Pushet 5 	Stakk: (0, 5)
- Shiftet 5 	Stakk: (0)
- Shiftet 0 	Stakk: ()

Side 8: Oppsummering

Oppsummering

I dag har vi lært den enkleste måten å lagre sekvensiell data på, med arrays. Vi har gjennomgått hvordan de opprettes, hvordan man blar gjennom dem, hva man kan slå opp etter, hvordan de sorteres, de vanligste operasjonene man gjør på et array og til slutt hvordan de fungerer som køer og stakker.

Det er flere ting vi ikke har gått gjennom her; multi-dimensjonale arrays er en av disse tingene. Ved å plassere arrays inne i arrays kan du lage relativt komplekse lagringsstrukturer som trær og matriser. Du skal i løpet av dette kapittelet ha fått nok kunnskap til å eksperimentere med dette selv.

I neste kapittel skal vi gå gjennom funksjoner, hva de brukes til og hvordan man lager sine egne.