Aller au contenu

Bug de PHP ou c'est moi ?


Sujets conseillés

Posté (modifié)

Bonjour,

j'ai un problème bizarre, je mets le même shéma que j'ai dans mon script.

Est-ce que quelqu'un peut tester et me dire si il il voit "un, deux, trois" ou un ordre différent svp ?

$tab = array();

$tab['pos1']['k1'][] = array('value' => 'deux','priority' => 1.5);
$tab['pos1']['k1'][] = array('value' => 'trois','priority' => 1.5);

$tab['pos2']['k1'][] = array('value' => 'une valeur pos1 / k1','priority' => 1.5);
$tab['pos1']['k2'][] = array('value' => 'une valeur pos1 / k1','priority' => 1.5);

$tab['pos1']['k1'][] = array('value' => 'une','priority' => 1.4);

// Du plus petit au plus grand
function compare($a, $
{
if ($a['priority'] == $b['priority']) return 0;
return ($a['priority'] < $b['priority']) ? -1 : 1;
}
uasort($tab['pos1']['k1'],'compare');

var_dump($tab['pos1']['k1']);

Le seul moyen que j'ai trouvé pour que ça fonctionne est de faire un array_reverse avant le trie (uasort) :

$tab['pos1']['k1'] = array_reverse($tab['pos1']['k1']);

Je trouve ça illogique d'inverser le tableau avant le trie, à moi qu'il y ait une raison que j'ignore ?

Si il n y a pas de raison logique, je préfère trouver une autre solution que de faire de la magie :wacko:

Quelqu'un aurait une idée de comment faire un trie en respectant l'ordre naturel d'assignation sauf si la priorité (priority) l'impose ?

Merci pour votre aide car là j'ouvre la fenêtre parce que j'ai de la fumé qui sort par les oreilles ...

Edit : pour infos ma version est PHP5.3

Modifié par Occi
Posté

Salut,

Il me semble que si tu remplaces ça :

if ($a['priority'] == $b['priority']) return 0;

par :

if ($a['priority'] == $b['priority']) return 1;

Tu forceras php à garder l'ordre naturel d'assignation en cas d'égalité de 'priority' ;)

Posté

Ca m'épaterait beaucoup ça, perso. Ca revient à dire que lorsque deux priorités sont égales l'une est plus grande que l'autre, sans trop savoir qui est qui. Ca pourrait même aboutir à des boucles sans fin avec certains algos de tri.

De façon générale, les fonctions de tri respectent l'ordre qui leur est donné par la fonction de comparaison, et l'ordre initial est ignoré (même si en fonction de l'algo utilisé celui-ci peut avoir une influence, rien ne le garantit).

Si tu veux respecter l'ordre initial, il faut que tu ajoutes un champ qui contient cet ordre, et qu'il soit utilisé par ta fonction de comparaison comme second critère de tri.

Par exemple, tu ajoutes un ['initial_order'] à chaque valeur (avec une bête boucle for), puis dans ta fonction compare tu fais:

return ($a['priority'] - $b['priority']) || ($b['initial_order'] - $a['initial_order']);

Au passage, il ne me semble pas que uasort soit pertinent ici, usort devrait largement suffire (mais moi et le php...).

Jacques.

Posté

Effectivement Jacques a raison, ma solution ne peut pas fonctionner, car au fur et à mesure du tri, l'ordre évolue.

Apparemment autrefois cette fonction prenait l'ordre initial en compte, j'ai lu ça sur http://www.manuelphp.com/ (pour la fonction usort) :

Si deux éléments sont égaux, au sens de la fonction cmp_function , leur ordre sera indéfini. Jusqu'en PHP 4.0.6, la fonction de tri leur conserverait leur ordre original, mais le nouvel algorithme introduit en PHP 4.1.0 fait que ce n'est plus le cas, car cela serait trop coûteux.

Du coup maintenant, la seule solution semble être d'ajouter un second critère de tri comme expliqué par Jacques.

Posté

Yes c'est ça ! Un grand merci à vous 2 !

return ($a['priority'] - $b['priority']) || ($b['initial_order'] - $a['initial_order']);

Ne fonctionne pas mais la logique est bonne, y compris ce que tu dis Ernestine :

if ($a['priority'] == $b['priority']) return 1;

ne fonctionne pas pour les raisons vues plus haut mais dans ce cas il faut bien retourner -1 ou 1 pour forcer l'ordre (en se basant sur l'inital_order).

Ce qui donne pour ceux qui en auraient l'utilité :

// Du plus petit au plus grand
function compare($a, $
{
if($a['priority'] == $b['priority'])
return ($a['initial_order'] < $b['initial_order']) ? -1 : 1;

return ($a['priority'] < $b['priority']) ? -1 : 1;

}

Veuillez vous connecter pour commenter

Vous pourrez laisser un commentaire après vous êtes connecté.



Connectez-vous maintenant
×
×
  • Créer...