Indice del forum Olimpo Informatico
I Forum di Zeus News
Leggi la newsletter gratuita - Attiva il Menu compatto
 
 FAQFAQ   CercaCerca   Lista utentiLista utenti   GruppiGruppi   RegistratiRegistrati 
 ProfiloProfilo   Messaggi privatiMessaggi privati   Log inLog in 

    Newsletter RSS Facebook Twitter Contatti Ricerca
Corso base di Php - Lezione 5
Nuovo argomento   Rispondi    Indice del forum -> Linguaggi per Internet
Precedente :: Successivo  
Autore Messaggio
freemind
Supervisor sezione Programmazione
Supervisor sezione Programmazione


Registrato: 04/04/07 20:28
Messaggi: 4643
Residenza: Internet

MessaggioInviato: 29 Giu 2009 22:26    Oggetto: Corso base di Php - Lezione 5 Rispondi citando

Eccoci con un'altra lezioncina sul php.
Della serie: "A volte ritornano" oggi facciamo la conoscenza dei costrutti iterativi.

Costrutti iterativi
Capita spesso e volentieri di dover ripetere la stessa cosa più volte, per un certo numero di volte oppure mentre vale una condizione: per fare tutto ciò php mette a disposizione i seguenti costrutti:
Codice:

while(condizione)
{
   ...
}

do
{
   ...
}
while(condizione);

for(inizializzazione;condizione;alterazione)
{
   ...   
}

foreach (oggetto iterebile as $valore)
{
   ...   
}

foreach (oggetto iterebile as $chiave => $valore)
{
   ...   
}


Iniziamo a parlare di while.
Questo costrutto cicla le istruzioni al suo interno mentre la condizione "condizione" è vera; per definire la condizone possiamo usare gli operatori utilizzati con la if.
Vediamo un esempio scemo (come tutti gli esempi che propongo io):
Codice:

<?
   $x=360;
   
   while ($x%2==0)
   {
      print $x . '<br/>';
      
      $x/=3;   // $x=$x/3;
   }
?>

Il precedente esempio stampa il valore di $x e poi lo divide per 3 fino a quando non otteniamo come risultato un numero dispari.
Tenete presente che potremmo non entrare mai nel ciclo: se $x venisse inizializzata con un numero dispari, l'esempio precedente non stamperebbe mai nulla.
In pratica while controlla la condizione all'inizio della sua esecuzione oppure quando l'ultima istruzione viene eseguita, prima di ricominciare con la prima.
Abbiamo la possibilità di spostare il controllo in fondo tramite do...while(...)
Codice:

<?
   $x=361;
   
   do
   {
      print $x . '<br/>';
      
      $x/=3;   // $x=$x/3;
   }
   while ($x%2==0);
?>


Quando sappiano il numero esatto di volte per le quali verrà ripetuta una serie di istruzioni possiamo usare for.
L'esempio che segue stampa i primi 10 numeri naturali:
Codice:

<?
   for ($i=0;$i<10;++$i)
   {
      print $i . '<br/>';   
   }
?>

La struttura del for prevede che ci siano una serie di var inizializzate; un controllo; una serie di alterazioni sulle variabili.
Tenete presente che il for di php non è come quello di VB; di fatto qui abbiamo solo una riscrittura del while. Possiamo creare cicli all'indietro:
Codice:

<?
   for ($i=9;$i>=0;--$i)
   {
      print $i . '<br/>';   
   }
?>

oppure creare cicli for su due contatori
Codice:

<?
   for ($i=0,$j=19;$i<10 || $j>=0;++$i,--$j)
   {
      print $i . ' - ' . $j . '<br/>';
   }
?>

Per come abbiamo scritto il for precedente stamperemo di fatto le coppie $i - $j fino a che $j non varrà -1.
Il risultato non sarebbe cambiato (in questo caso) se la condizione sulla $i fosse stata omessa.
Non siamo obbligati a controllare una var definita nell'intestazione del for:
Codice:

<?
   $k=0;
   for($i=0;$k<3;++$i)
   {
      print $i . '<br/>';
      ++$k;   
   }   
?>

e in realtà potremmo omettere qualunque parte dell'intestazione:
Codice:

<?
   $k=0;
   for(;$k<3;++$k)
   {
      print $i . '<br/>';
   }   
?>

oppure riscriverlo tramite:
Codice:

<?
   $k=0;
   for(;$k<3;)
   {
      print $i . '<br/>';
      ++$k;
   }   
?>

Questo di fatto rappresenta un ciclo while a tutti gli effetti.
Potremmo scrivere anche:
Codice:

<?
   for(;1==1;)
   {
      ...
   }
?>

creando un loop infinito (vale anche per while e do...while) che però di solito si semplifica con:
Codice:

<?
   for(;;)
   {
      ...
   }
?>


Possiamo anche alterare l'andamento di un ciclo (qualunque sia) usando "break" o "continue".
Per stampare i primi 10 numeri pari possiamo scrivere:
Codice:

<?
   for ($i=0,$k=0;$k<10;++$i)
   {
      if ($i%2==0)
      {
         print $i;
         ++$k;
      }
      else
         continue;
         
      print ' (' . $k . ')';
      
      print '<br/>';
   }
?>

Quando $i contiene un numero dispari il continue salta alla fine e poi il for riprende normalmente.

In caso volessimo fermare un ciclo prima che la condizione di esecuzione diventi falsa possiamo usare "break":
Codice:

<?
   for ($i=0;$i<10;++$i)
   {
      print $i . '<br/>';
      if ($i==5)
         break;   
   }
?>

e così anche se il ciclo dovrebbe terminare con $i==10 si blocca con $i==5.

Quando usiamo gli array i cicli diventano indispensabili. Di seguito vedremo due esempi che poi riprenderò con le funzioni: anche se esistono funzioni per ordinare gli array, implementeremo un algoritmo elementare chiamato Bubble Sort che ordina un vettore in senso crescente.
l'idea è la seguente:
1. si confronta il primo elemento con il secondo e se questo è minore del primo li si scambia
2. si ripete fino a confrontare il penultimo numero con l'ultimo.
3. a questo punto abbiamo che all'ultimo posto del vettore si troverà il numero più grande
4. ricominciamo come con 1. fino però ad arrivare a confrontare il terzultimo con il penultimo e così via...
Codice:

<?
   $arr=array();
   
// inizializizzo il vettore
   for ($i=10;$i>0;--$i)
      $arr[]=$i;
      
   print '<pre>';
   print_r($arr);
   print '</pre>';
   
// ordino
   for ($i=count($arr)-1;$i>0;--$i)
   {
      for ($j=0;$j<$i;++$j)
      {
      // scambio
         if ($arr[$j]>$arr[$i])
         {
            $tmp=$arr[$i];
            $arr[$i]=$arr[$j];
            $arr[$j]=$tmp;
         }
      }
   }
   
   print '<pre>';
   print_r($arr);
   print '</pre>';
?>

Possiamo migliorare l'algoritmo facendo la seguente osservazione: se durante il ciclo interno non facciamo scambi allora il vettore è ordinato quindi possiamo fermarci.
L'implementazione diventa:
Codice:

<?
   $arr=array();
   
// inizializizzo il vettore
   for ($i=10;$i>0;--$i)
      $arr[]=$i;
      
   print '<pre>';
   print_r($arr);
   print '</pre>';
   
// ordino
   $n=count($arr)-1;
   
   do
   {
      $ordinato=true;
      
      for($i=0;$i<$n;++$i)
      {
         if ($arr[$i]>$arr[$i+1])
         {
            $tmp=$arr[$i];
            $arr[$i]=$arr[$i];
            $arr[$i]=$tmp;
            
            $ordinato=false;
         }
      }
      
      --$n;
      
   }
   while(!$ordinato);
   
   print '<pre>';
   print_r($arr);
   print '</pre>';
?>

partendo con un vettore ordinato in senso inverso abbiamo le stesse prestazioni; negli altri casi potremmo subire un aumento di velocità perchè di fatto il numero di cicli "inutili" nei quali non avvengono scambi diminuisce.

L'ultimo costrutto iterativo che prendiamo in considerazione è il foreach.
E' di fatto una variante al ciclo for (in altri linguaggi viene detto "ciclo for migliorato") e si presenta in due forme generali:
Codice:

foreach (oggetto iterabile as $valore)
{
   ...
}

oppure
Codice:

foreach (oggetto iterabile as $key => $valore)
{
   ...
}

e al momento per noi l'oggetto iterabile sarà sempre un array.
Normalmente quando dobbiamo ciclare all'interno di un vettore utilizziamo il costrutto for perchè cade proprio a pennello.
Inoltre con il for possiamo anche modificare i valori del vettore oppure possiamo stampare a video solo gli elementi con indice dispari (ad esempio). Un modo più semplice di visitare un vettore, nel caso in cui dobbiamo per esempio stamparne tutti i valori viene dato invece dal foreach. Di fatto possiamo interpretare il costrutto come "per ogni elemento del vettore dammi il suo valore" oppure "per ogni elemento del vettore dammi la chiave e il valore".
Vediamo subito un esempio:
Codice:

<?php
   $vettore = array
   (
      'Ciao',
      'Pluto',
      'Pippo',
      'Casa'
   );
   
   foreach ($vettore as $value)
   {
      print $value . '<br/>';
   }
?>

Il nostro vettore viene inizializzato con 4 valori e poi viene stampato tramite il ciclo.
Il foreach itera per ogni elemento del vettore; l'elemento attualmente preso in considerazione viene copiato dentro a $value (avremmo potuto usare un altro nome) e così noi possiamo farci qualche cosa.
Se volessimo stampare anche l'indice dell'elemento potremmo utilizzare la seconda forma:
Codice:

<?php
   $vettore = array
   (
      'Ciao',
      'Pluto',
      'Pippo',
      'Casa'
   );
   
   foreach ($vettore as $key => $value)
   {
      print $key . ' - ' . $value . '<br/>';
   }
?>

Anche qui $key è un nome scelto da noi.
Quando dobbiamo elaborare in sequenza tutti gli elementi di un vettore questa notazione risulta più elegante rispetto al for classico.
Nulla vieta che $value sia lui stesso un vettore:
Codice:

<?php
   $vettore = array
   (
      array('Ciao','Casa','Mucca'),
      array('Fattoria','Nonno','Cane'),
      array('Uva','Mela','Limone')
   );
   
   foreach ($vettore as $key => $value)
   {
      print $key . ' - ';
      foreach ($value as $v)
      {
         print $v . ' ';
      }
      print '<br/>';
   }
?>

e come potete notare da soli abbiamo la possibilità di nidificare i cicli.
L'esempio stampa per ogni elemento di $vettore, l'indice e il contenuto dell'attuale riga poi va a capo e ricomincia.

Ricordate che se passate come primo parametro un oggetto non iterabile, ad esempio una variabile definita come "$a=3", php genererà un errore.

Nelle due forme precedenti non possiamo modificare gli elementi del vettore perchè in realtà l'elaborazione avviene su una copia; $value contiene il valore corrente ma non un riferimento allo stesso percui la seguente non produce modifiche su $vettore:
Codice:

<?php
   $vettore = array
   (
      'Ciao','Casa','Mucca'   
   );
   
   foreach ($vettore as $value)
   {
      $value=9;
   }
   
   print '<pre>';
   print_r($vettore);
   print '</pre>';
?>

Se abbiamo la necessità di alterare il contenuto degli elementi $value deve essere passato per referenza nel modo seguente:
Codice:

<?php
   $vettore = array
   (
      'Ciao','Casa','Mucca'   
   );
   
   foreach ($vettore as &$value)   // notate la &
   {
      $value=9;
   }
   
   print '<pre>';
   print_r($vettore);
   print '</pre>';
?>

In questo caso dopo il ciclo ogni elemento del vettore sarà uguale a 9.
Il concetto di referenza verrà spiegato bene nel capitolo sulle funzioni.

Personalmente preferisco in un caso del genere usare però un ciclo for, lo ritengo più leggibile.

E qui finiamo con i cicli.
Mi raccomando, scrivete, bestemmiatemi dietro e chiedete pure!
freemind
Top
Profilo Invia messaggio privato
leonte54
Mortale devoto
Mortale devoto


Registrato: 28/07/12 08:44
Messaggi: 5

MessaggioInviato: 28 Lug 2012 08:57    Oggetto: Rispondi citando

Ciao,
ho trovato questa lezione molto interessante, sopratutto per me che sono un neofita.
Stavo appunto facendo degli esercizi di ordinamento e volevo ordinare un array con foreach mantenendo la chiave originale, visto che con il ciclo for le chiavi vengono reindicizzate.
Hai qualche consiglio da darmi senza utilizzare la funzione asort?

Grazie e ancora complimenti.

Giuseppe
Top
Profilo Invia messaggio privato
freemind
Supervisor sezione Programmazione
Supervisor sezione Programmazione


Registrato: 04/04/07 20:28
Messaggi: 4643
Residenza: Internet

MessaggioInviato: 28 Lug 2012 11:00    Oggetto: Rispondi citando

Ciao leonte54,
benvenuto e grazie.

Deduco che tu voglia ordinare un array associativo (quindi le chiavi non sono indici numerici) ed in oltre vuoi che restino collegate le chiavi ai loro valori.

Se il problema che hai è proprio questo allora usa asort che fa proprio quello che chiedi. Con questa funzione l'array:
Codice:

$x=array('a'=>4,'b'=>3,'c'=>2,'d'=>1);

dopo la chiamata:
Codice:

asort($x);

diventa:
Codice:

$x=array('d'=>1,'c'=>2,'b'=>3,'a'=>4);

Ossia un array di numeri ordinato in senso crescente con le chiavi associative collegati ai loro valori iniziali.

Se invece l'array che vuoi ordinare ha indici numeri (e quindi posizionali) allora ha senso che dopo l'ordinamento le chiavi risultino non alterate (0,1,2,3,4...) ma i valori sì.

Se ho capito male il tuo problema dimmelo che vediamo più in dettaglio.
Ciao
Top
Profilo Invia messaggio privato
leonte54
Mortale devoto
Mortale devoto


Registrato: 28/07/12 08:44
Messaggi: 5

MessaggioInviato: 28 Lug 2012 15:25    Oggetto: Rispondi citando

Ti ringrazio per la risposta.
Come accennato, essendo un esercizio, non vorrei utilizzare asort ma cercare di capire come creare un algoritmo simile.
L'array ha valori INT con chiavi assegnate per default, con foreach vorrei ordinarle in ordine crescente per poi visualizzarle a video con le relative chiavi originali.
Codice:

$arr=array(8, -5, 34, 22);

Output:
Codice:

[1]=>-5
[0]=>8
[3]=>22
[2]=>34

Inoltre non vorrei utilizzare le funzioni perché non le ho ancora studiate.
Ti ringrazio per la disponibilita'
Top
Profilo Invia messaggio privato
freemind
Supervisor sezione Programmazione
Supervisor sezione Programmazione


Registrato: 04/04/07 20:28
Messaggi: 4643
Residenza: Internet

MessaggioInviato: 28 Lug 2012 16:44    Oggetto: Rispondi citando

Chiaro...
Dunque, quello che chiedi è un po' inusuale ma si può fare.
Il giochino che sta alla base di tutto (almeno, quello che è venuto in mente a me) è che occorre avere un array con le chiavi di partenza da ordinare insieme all'array dei valori in modo che i valori del vettore di partenza alla fine siano nello stesso posto dei valori che rappresentano le loro chiavi originali nel vettore delle chiavi.
E' un giro di parole maledetto ma adesso di posto due righe di codice:
Codice:

<?php
$arr=array(5,4,3,2,1,0);   // array da ordinare
$keys=array_keys($arr);      // array che contiene le chiavi di $arr

print '<pre>';
print 'prima<br/>';
print_r($arr);
print_r($keys);
print '</pre>';

// bubble-sort elementare per ordinare l'array
for ($i=count($arr)-1;$i>0;--$i)
{
   for ($j=0;$j<$i;++$j)
   {
      if ($arr[$j]>$arr[$j+1])
      {
      // scambio gli elementi del vettore
         $t=$arr[$j];
         $arr[$j]=$arr[$j+1];
         $arr[$j+1]=$t;
      // e di conseguenza anche le chiavi corrispondenti   
         $t=$keys[$j];
         $keys[$j]=$keys[$j+1];
         $keys[$j+1]=$t;
      }
   }
}

print '<pre>';
print 'dopo<br/>';
print_r($arr);
print_r($keys);
print '</pre>';

// questo è il vettore finale con gli elementi ordinati e le chiavi associate come all'inizio
$end=array();
for ($i=0;$i<count($keys);++$i)
{
   $end[$keys[$i]]=$arr[$i];
}

print '<pre>';
print 'fine<br/>';
print_r($end);
print '</pre>';


In pratica tiro fuori le chiavi del vettore e le metto in un array (usandole come valori).
A questo punto ordino l'array originale (e qui ho usato bubble-sort per scrivere poco).
Durante l'ordinamento se scambio nel vettore l'elemento 2 con il 3 allora scambio anche la chiave 2 con la 3 (nel senso che scambio i valori nel vettore delle chiavi alla posizione 2 e 3).
Alla fine avrò due array, il primo ordinato ma con le chiavi non associate e l'altro sarà un vettore con i valori ordinati in qualche modo (a noi sconosciuto).
Per costruzione sappiamo però che i due array hanno lo stesso numero di elementi e il primo valore del vettore delle chiavi è la chiave del primo elemento del vettore dei valori quindi con l'ultimo for costruiamo il vettore che volevi.

Non ho fatto molte prove ma mi sembra che funzioni. Qui l'ordinamento è in senso crescente e ho usato dei numeri come valori.
Il ragionamento è analogo per le stringhe o altri tipi di dati.
Top
Profilo Invia messaggio privato
leonte54
Mortale devoto
Mortale devoto


Registrato: 28/07/12 08:44
Messaggi: 5

MessaggioInviato: 28 Lug 2012 17:47    Oggetto: Rispondi citando

E' quasi la soluzione che avevo trovato
Codice:

<?php
$arr=array(5,4,3,2,1,0);
$arrK=array(); // array per le chiavi
$arrE=array(); // array finale

$c=count($arr); // calcolo il numero degli elementi nell'array
$v=1; // valore booleano true

for ($y=0; $y < $c; $y++) // ciclo destinato all'array per le chiavi
    $arrK[]=$y; // creo l'array per le chiavi partendo dall'y-esimo

$cc=count($arr)-1;

for ($i=0; ($i < $cc) && ($v == 1); $i++) {

   for ($j=0; $j < ($cc-$i); $j++) {
      if ($arr[$j] > $arr[$j+1]) {         
         $k=$arr[$j];
         $arr[$j]=$arr[$j+1];
         $arr[$j+1]=$k;
          
         $kk=$arrK[$j]; 
         $arrK[$j]=$arrK[$j+1];
         $arrK[$j+1]=$kk;
      }
   }
}

for ($x=0; $x < $c; $x++) $arrE[$arrK[$x]]=$arr[$x];

// stampo a video le chiavi e i valori dell'array finale
foreach($arrE as $chiave => $valore)
print "[$chiave] => $valore<br />";
?>

Avrei desiderato invece utilizzare il foreach, pensi non sia possibile?

Grazie
Top
Profilo Invia messaggio privato
freemind
Supervisor sezione Programmazione
Supervisor sezione Programmazione


Registrato: 04/04/07 20:28
Messaggi: 4643
Residenza: Internet

MessaggioInviato: 28 Lug 2012 17:58    Oggetto: Rispondi citando

Il foreach lo puoi usare nella forma:
Codice:

foreach ($array as $k=>$v)
{
...
}

però sinceramente non ne vedo il motivo dato che hai indici numerici.
Il foreach non ti aiuta a mantenere le chiavi associate, o almeno, a me non viene in mente come lo si possa usare in tal senso.
Dovrai comunque costruire un array di chiavi etc...

Perchè vuoi proprio questo tipo di ciclo?
Top
Profilo Invia messaggio privato
leonte54
Mortale devoto
Mortale devoto


Registrato: 28/07/12 08:44
Messaggi: 5

MessaggioInviato: 28 Lug 2012 18:28    Oggetto: Rispondi citando

Ok, ti ringrazio
Top
Profilo Invia messaggio privato
leonte54
Mortale devoto
Mortale devoto


Registrato: 28/07/12 08:44
Messaggi: 5

MessaggioInviato: 28 Lug 2012 18:32    Oggetto: Rispondi citando

Scusa non avevo letto l'ultimo rigo dove mi chiedevi il motivo.

Volevo sapere appunto se con il foreach fosse possibile, magari sai come sia possibile risalire all'algoritmo asort e vedere come agisce?

Ultimo consiglio, sapresti indicarmi un testo che mi possa aiutare a come strutturare un algoritmo.

grazie
Top
Profilo Invia messaggio privato
freemind
Supervisor sezione Programmazione
Supervisor sezione Programmazione


Registrato: 04/04/07 20:28
Messaggi: 4643
Residenza: Internet

MessaggioInviato: 28 Lug 2012 18:52    Oggetto: Rispondi citando

Guarda, io non ho idea di quale algoritmo usi asort; la cosa più simile a quella funzione applicata ad un array con chiavi numeriche è quella che ti ho postato e che di fatto è una variante della tua.

Un testo sugli algoritmi?
Beh, sicuramente i testi didattici per i corsi di programmazione però poi dipende un po' da cosa vuoi studiare: se cerchi roba specifica sull'analisi numerica, sulla crittografia, algoritmi genetici... insomma, è un po' varia la letteratura.
Top
Profilo Invia messaggio privato
SverX
Supervisor Macchinisti
Supervisor Macchinisti


Registrato: 25/03/02 11:16
Messaggi: 11559
Residenza: Tokelau

MessaggioInviato: 03 Ago 2012 16:57    Oggetto: Rispondi citando

io invece non capisco proprio il senso di ordinare un array associativo, se con ogni valore voglio ordinare ogni sua chiave. Cioè tutto rimane come prima, alla fine, no? Confused
Top
Profilo Invia messaggio privato HomePage
freemind
Supervisor sezione Programmazione
Supervisor sezione Programmazione


Registrato: 04/04/07 20:28
Messaggi: 4643
Residenza: Internet

MessaggioInviato: 03 Ago 2012 18:37    Oggetto: Rispondi

Mumble... io in varie occasioni ho dovuto farlo perchè l'array associativo era in realtà una struttura dati di comodo costruita secondo un certo criterio e che alla fine necessitava un ordinamento sulle chiavi (che avevano un significato ben preciso).
Costruire la struttura già ordinata non era fattibile e usare altri sistemi tipo grafi o alberi era troppo macchinoso per il tempo a disposizione.

Ammetto che non è proprio la norma comunque imbattersi in un problema del genere.
Top
Profilo Invia messaggio privato
Mostra prima i messaggi di:   
Nuovo argomento   Rispondi    Indice del forum -> Linguaggi per Internet Tutti i fusi orari sono GMT + 1 ora
Pagina 1 di 1

 
Vai a:  
Non puoi inserire nuovi argomenti
Non puoi rispondere a nessun argomento
Non puoi modificare i tuoi messaggi
Non puoi cancellare i tuoi messaggi
Non puoi votare nei sondaggi