Page 1 sur 1

tri d'un tableau multidimensionel

Posté : 10 mars 2007, 20:14
par jojolapine
bonjour à tous,
je cherche à trier un tableau multi dimensionnel...
de cette forme:

Code : Tout sélectionner

Array ( [0] => Array ( [date] => 1197455400 [lieu] => ihih [description] => hioh ) [1] => Array ( [date] => 1184265000 [lieu] => oh [description] => vvr ) [2] => Array ( [date] => 1184265000 [lieu] => oh [description] => vvr ) [3] => Array ( [date] => 1194809400 [lieu] => içi [description] => répète ) [4] => Array ( [date] => 1197578700 [lieu] => lens [description] => concert ) )
et je voudrai pouvoir trier selon la date le lieu ou la description...
seulement j'ai essayer avec uasort, mais je ne sais pas comment faire pour trier juste sur une colonne...
j'ai essayer ceci:
function time_sort($a,$b){
            if($a==$b) return 0;
            return ($a < $b) ? -1 : 1;
        }
        
        
        uasort($donnees,'time_sort');
seulement ça ne tri pas comme il faut il me semble...
puisque je ne dis à aucun moment quelle entrée utiliser...
Un peu d'aide siouplé... :oops:
merci d'avance!

Posté : 10 mars 2007, 20:43
par Jules Petibidon
hello,

tu tries des tableaux, donc dans ta fonction tu dois spécifier les clés qui doivent etre triées, sinon il compare array à array ce qui donne pas grand chose ;)

donc essaye ceci :
function time_sort($a,$b){
            if($a['date']==$b['date']) return 0;
            return ($a['date'] < $b['date']) ? -1 : 1;
        }
accessoirement j'ai du mal à capter la différence entre uasort() et usort()

Posté : 10 mars 2007, 20:49
par titerm
Tu n'es pas loin du compte encore que la fonction tri est tjs un peu compliqué ... mais j'ai l'impression que chez toi, c'est une marque de fabrique ;)

function time_sort($a,$b){
	return($a['date']-$b['date']);
}

Posté : 10 mars 2007, 20:54
par titerm
Grillé par jules...

La différence avec uasort, c'est que uasort va préserver les clés d'index, le trie ne se verra que par un parcour du tableau via un foreach ou autre.

usort ne preserve pas les index... Dans l'exemple de jojo, avec usort, ton tableau de sortie sera trié et les index iront de 0 a 4, avec uasort, il seront maintenu comme a l'origine. tu auras donc 1,2,3,0,4 ds le cas présent si on tri sur la date

Posté : 10 mars 2007, 21:43
par jojolapine
mais j'ai l'impression que chez toi, c'est une marque de fabrique
Qu'est-ce que tu veux dire par là ? :? Sinon je regarde plus tard..pas le temps là....

Posté : 10 mars 2007, 23:50
par titerm
Je veux dire que tu as l'air de bien aimer faire compliquer qd on peut faire simple... :lol:

Posté : 11 mars 2007, 15:48
par jojolapine
oui mais là c'est un peu plus compliqué que ça...
Car la colonne selon laquelle je souhaite trier... est variable, et en fonction de la demande... donc la clé doit être variable, peut-être en faisant quelque chose comme ça:
$colonne='date';
$time_sort = create_function('$a,$b', 'return($a[\''.$colonne.'\']-$b[\''.$colonne.'\']);');
mais après je ne sais pas comment dire à uasort() de prendre cette fonction...
est-ce que les fonctions anonymes se désignent de la même manière que les autres ?

Posté : 11 mars 2007, 18:39
par jojolapine
bon et bien j'ai résolu tout seul :)
Voici ce que j'ai fait:
function orderby($donnees,$col,$sens){
        
        $function=  'if($a[\''.$col.'\']==$b[\''.$col.'\']) return 0;'.
                    'return ($a[\''.$col.'\'] '.($sens=='desc' ? '<' : '>').' $b[\''.$col.'\']) ? -1 : 1;';
        
        uasort($donnees,create_function('$a,$b',$function));
        
        
        return $donnees;
    }
résolu!!

Posté : 12 mars 2007, 17:17
par titerm
Pk pas... mais c'est toujours aussi compliqué... :)))

En plus, ca ne marchera pas si le tri a lieu sur une chaine. En l'occurence, un tri par lieu ou description ici...

Quitte a faire compliqué, voila une version objet qui trie aussi les strings

class mySort {
	const ASC = 1 ;
	const DSC = -1;
	static private $field;
	static private $order;

	static private function usort($a, $b) {
		if(is_numeric($a) && is_numeric($b)) {
			return ($a[self::$field] - $b[self::$field]) * self::$order;
		}
		return strcmp($a[self::$field],$b[self::$field]) * self::$order;
	}
	
	static private function setSort($f, $o) {
		self::$field = $f;
		self::$order = $o;
	}
	static public function sort(&$data, $field, $order=self::ASC) {
		self::setSort($field,$order);
		uasort($data,array('mySort','usort'));
	}
}


$foo = array (
	1=> array('age' => 30,'poids'=>60,'prenom'=>'joe'),
	2=> array('age' => 50,'poids'=>66,'prenom'=>'bill'),
	3=> array('age' => 50,'poids'=>55,'prenom'=>'tom'),
	4=> array('age' => 10,'poids'=>55,'prenom'=>'joe'),
);


print_r($foo);
mySort::Sort($foo,'prenom',mySort::DSC);
print_r($foo);
mySort::Sort($foo,'age');
print_r($foo);



Posté : 12 mars 2007, 18:18
par jojolapine
bon ok ma fonction marche mal pour les chaines de caractères, je la change donc en ceci:
function orderby($donnees,$col,$sens){

  if(is_numeric($a) && is_numeric($b)) { 
    $function='return ($a[\''.$col.'\'] - $b[\''.$col.'\']) * '.$sens.';';
  } else {
    $function='return strcmp($a[\''.$col.'\'],$b[\''.$col.'\']) * '.$sens.';';
  }

  uasort($donnees,create_function('$a,$b',$function));


  return $donnees;
}
c'est mieux comme ça...?
Pourquoi vouloir absolument faire une classe ? d'autant plus que cette fonction est d'ja dans une classe donc bon...

Posté : 12 mars 2007, 18:34
par titerm
Une classe parce que je trouve ca plus maintenable, c'est un outil que tu peux réutiliser ailleur. Et tout le code qui gère le tri est dedans... Donc en cas d'évolution, t as un ptit fichier avec juste ce qui doit évoluer dedans.
Quand on travaille a plusieurs sur un gros site, c'est bien de ne pas avoir des fichier qui font trop de chose... Sinon, ca pose problème et on passe son temps a merger lors du commit dans subversion (ou autre)

Ceci étant dit. Si tu es déjà dans une classe, pourquoi ne pas faire une fonction de tri dans ta classe ? La tu fais un create function qui est dur a lire, chiant a maintenir, et qui n'apporte rien. En plus, si tu as un optimisateur/cache d'opcode, c'est pas ce qui y a de plus efficace.

Enfin, pourquoi utiliser une copie des données, travail avec des références, la copie dans le cas présent n'a aucun interret si ce n'est de consomer de la mémoire et de la cpu. (met un & dans la signature de ta fonction avant le $données, et ne fait pas de return.

Si tu tiens absolument a faire des créate function, alterne les quote et les guillemets, c'est plus lisible que des \' (de mon poins de vue)

genre
$func = 'return ($a["' . $col.'"] - $b["' . $col.'"] ) * ' . $sens . ';' ;