tri d'un tableau multidimensionel

ViPHP
ViPHP | 3607 Messages

10 mars 2007, 20:14

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!

Eléphant du PHP | 259 Messages

10 mars 2007, 20:43

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()

Mammouth du PHP | 505 Messages

10 mars 2007, 20:49

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']);
}
Modifié en dernier par titerm le 10 mars 2007, 21:30, modifié 1 fois.

Mammouth du PHP | 505 Messages

10 mars 2007, 20:54

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

ViPHP
ViPHP | 3607 Messages

10 mars 2007, 21:43

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à....

Mammouth du PHP | 505 Messages

10 mars 2007, 23:50

Je veux dire que tu as l'air de bien aimer faire compliquer qd on peut faire simple... :lol:

ViPHP
ViPHP | 3607 Messages

11 mars 2007, 15:48

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 ?

ViPHP
ViPHP | 3607 Messages

11 mars 2007, 18:39

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!!

Mammouth du PHP | 505 Messages

12 mars 2007, 17:17

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);



ViPHP
ViPHP | 3607 Messages

12 mars 2007, 18:18

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...

Mammouth du PHP | 505 Messages

12 mars 2007, 18:34

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 . ';' ;