Newsgroup: it.comp.www.php
Titolo: [SPECIALE PRINCIPIANTI] riordino array multipli

Una struttura molto utile in PHP e' l'array multiplo, cioe' con piu'
di una chiave: praticamente un array di array.
A volte puo' capitare di dover riordinare un array in base ad una
delle chiavi secondarie, ed il manuale ufficiale PHP non offre molto
aiuto.
Ecco una soluzione pratica per piccoli array, che permette una
semplice manipolazione anche a chi e' alle prime armi in PHP.
- Esempio pratico -  
Immaginiamo di avere un archivio di pezzi di ferramenta, suddiviso in
articoli raggruppati per codice in questo modo:
<?
$pezzo["a1"]["marca"] = "beta";
$pezzo["a1"]["nome"] = "martello";
$pezzo["a1"]["prezzo"] = "6.50";
$pezzo["a2"]["marca"] = "pastorino";
$pezzo["a2"]["nome"] = "chiave 6 mm";
$pezzo["a2"]["prezzo"] = "2.50";
$pezzo["a3"]["marca"] = "pastorino";
$pezzo["a3"]["nome"] = "chiave 12 mm";
$pezzo["a3"]["prezzo"] = "5.50";
$pezzo["a4"]["marca"] = "pastorino";
$pezzo["a4"]["nome"] = "chiave 14 mm";
$pezzo["a4"]["prezzo"] = "5.75";
$pezzo["a5"]["marca"] = "usag";
$pezzo["a5"]["nome"] = "chiave 14 mm";
$pezzo["a5"]["prezzo"] = "5.82";
$pezzo["a5"]["marca"] = "valex";
$pezzo["a5"]["nome"] = "chiave 14 mm";
$pezzo["a5"]["prezzo"] = "3.50";
$pezzo["a5"]["marca"] = "usag";
$pezzo["a5"]["nome"] = "chiave 32 mm";
$pezzo["a5"]["prezzo"] = "15.40";
$pezzo["a6"]["marca"] = "beta";
$pezzo["a6"]["nome"] = "cacciavite 12 mm";
$pezzo["a6"]["prezzo"] = "5.50";
$pezzo["a6"]["marca"] = "valex";
$pezzo["a6"]["nome"] = "cacciavite 12 mm";
$pezzo["a6"]["prezzo"] = "2.45";
?>
Ed un array contenente le varie marche:
<?
$marche = array("beta", "usag", "valex", "pastorino", "wurth");
?>
Se vogliamo vedere quali prodotti abbiamo, raggruppandoli in una
tabella per marca ed in un'altra tabella per nome possiamo fare cosi':
<?
$SEP = "!"; # carattere separatore
sort($marche); # prima riordiniamo le marche
foreach($pezzo as $key=>$value) {
    $PerMarca[$key] = $value["marca"] . $SEP .
        $value["nome"] . $SEP . $value["prezzo"];
    $PerNome[$key] = $value["nome"] . $SEP .
        $value["marca"] . $SEP . $value["prezzo"];
}
asort($PerMarca); # riordiniamo per marca
asort($PerNome); # riordiniamo per nome
$Tabella1 = "";
foreach($marche as $m) {
    $Riga = "";
    $Titolo = "<b>$m</b><br>";
    foreach($PerMarca as $key=>$value) {
        if (preg_match("/^$m/",$value)) {
	    list($marca, $nome , $prezzo) = explode("$SEP", $value);
	    $Riga .= "art. $key - $nome - $prezzo &euro;<br>";
	}
    }
    if ($Riga>"") $Tabella1 .= "$Titolo$Riga<br>";
}
$Tabella2 = "<b>Elenco ordinato per nome</b><br>";
$Riga = "";
foreach($PerNome as $key=>$value) {
    list($nome, $marca, $prezzo) = explode("$SEP", $value);
    $Riga .= "art. $key - $nome - <b>$marca</b> - $prezzo &euro;<br>";
}
$Tabella2 .= "$Riga<br>";
echo $Tabella1;
echo $Tabella2;
?>
Come noterete nell'output, la marca "wurth" non viene visualizzata
perche' non ci sono articoli di quella marca nell'elenco.
Questo sistema va bene quando gli array non sono troppo grossi (in
genere non piu' di un centinaio di linee): coll'aumentare del volume
dei dati risulta molto piu' conveniente, in termini di prestazioni,
affidare i riordini a query MySql.
Puo' anche tornare utile quando i dati non provengono da una tabella
MySql ma da qualche altra parte, per esempio quando si lavora sui
filesystem.
Il trucchetto e' stato trovato sul sito 
http://www.tek-tips.com
cercando con Google 'php sort multidimensional array'.
Se non ci sono obiezioni passero' poi questo script nelle FAQ.
ciao!
-- 
Marco Bernardini - bernama chiocciola libero it
Per farvi strada nella vita non approfittate mai delle cariche che
vi sono state assegnate, a meno che non siate un minatore.

 vi sono state assegnate, a meno che non siate un minatore.
Tempo fa ho avuto lo stesso problema e mi sono scritto la seguente funzione
che riordina un array bidimensionale secondo un certo campo, lasciando o
meno preservato l'indice. Volendo č possibile cambiare l'algorimo di
ordinamento conun un po' piů performante.
Ciao,
Nico
<?
//Ordina un array bidimensionale secondo una certa
//colonna data. Se necessario preserva l'indice.
//Se si desidera ordinare per chiave passare $order_by = '_key'
function bidim_array_short($array, $order_by, $preserve_key = false ){
 //Se necessario converte l'array
 if ($preserve_key){
  $i=0;
  foreach($array as $key => $row){
   $tarray[$i] = $row;
   $tarray[$i]['_key'] = $key;
   $i++;
  }
  unset($array);
  $array = $tarray;
  unset($tarray);
 }
 //Ordina l'array
 do {
  $change = false;
  for ($i = 1; $i < count($array); $i++){
   if ($array[$i][$order_by] < $array[$i-1][$order_by]){
    $tarray = $array[$i];
    $array[$i] = $array[$i-1];
    $array[$i-1] = $tarray;
    $change = true;
   }
  }
 } while ($change == true);
 unset($tarray);
 //Se necessario ripristina l'array
 if ($preserve_key){
  foreach($array as $row){
   $tarray[$row['_key']] = array_slice ($row, 0, count($row)-1);
  }
  unset($array);
  $array = $tarray;
  unset($tarray);
 }
 //Ritorna l'array ordinato
 return ($array);
}
?>

 funzione che riordina un array bidimensionale 
 
Non male: come in tutti i linguaggi evoluti c'e' sempre piu' di un modo
per fare la stessa cosa!
-- 
bernama chiocciola libero it
Se in un cestino ho 2 mele e tolgo 2 mele ho
0 mele, ma anche 0 banane, 0 pere, 0 pesche.
Praticamente sono senza macedonia.

 Se non ci sono obiezioni passero' poi questo script nelle FAQ.
Hm, e' da vedere....
Usare uasort invece? Esempio:
function prezzoMarca($a, $b)
{
    $ret=$a['prezzo']-$b['prezzo'];
	// se prezzo uguale ordina per marca:
    if (!$ret)     
        $ret=strcmp($a['marca'], $b['marca']);
    return $ret;
}
uasort($pezzo, "prezzoMarca");
 
 

 Usare uasort invece? Esempio:
Ottima idea per la versione 0.02!
In effetti la mia e' una soluzione Quick&Dirty...
ciao
Marco
-- 
