6 votes

Comparaison de tableaux en PHP - comportement intéressant

Le premier exemple :

$x = array("a" => 1, "b" => 2); 
$y = array("b" => 1, "a" => 2);
$xLessY = ($x < $y);
$xGreaterY = ($x > $y);
var_dump($xLessY, $xGreaterY);

Résultat : $xLessY = vrai , $xGreaterY = vrai

Le deuxième exemple :

$x = array("a" => 2, "b" => 1); 
$y = array("b" => 2, "a" => 1);
$xLessY = ($x < $y);
$xGreaterY = ($x > $y);
var_dump($xLessY, $xGreaterY);

Résultat : $xLessY = faux , $xGreaterY = faux

Selon la documentation sur http://docs.php.net/manual/en/language.operators.comparison.php :

si la clé de l'opérande 1 n'est pas trouvée dans l'opérande 2. l'opérande 2, les tableaux sont non comparables, sinon - comparer valeur par valeur

Dans notre cas, chaque clé du tableau $x est présente dans le tableau $y, donc $x et $y sont comparables. Voir aussi l'exemple de la documentation :

// Arrays are compared like this with standard comparison operators
function standard_array_compare($op1, $op2)
{
    if (count($op1) < count($op2)) {
        return -1; // $op1 < $op2
    } elseif (count($op1) > count($op2)) {
        return 1; // $op1 > $op2
    }
    foreach ($op1 as $key => $val) {
        if (!array_key_exists($key, $op2)) {
            return null; // uncomparable
        } elseif ($val < $op2[$key]) {
            return -1;
        } elseif ($val > $op2[$key]) {
            return 1;
        }
    }
    return 0; // $op1 == $op2
}

Ce comportement est vraiment étrange : $x est inférieur à $y et en même temps $x est supérieur à $y (le premier exemple) et deux tableaux sont comparables.

Je pense que c'est parce que php compare toujours en commençant par le côté défini du signe '<'. Je veux dire : pour ($x < $y) php prend $x comme opérande 1, pour ($x > $y) il prend $y comme opérande 1. Bien que je n'ai rien trouvé sur ce comportement dans la documentation.
Qu'en pensez-vous ?

1voto

user187291 Points 28951

Votre hypothèse est correcte. Le site > est interprété comme

|   expr '>' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$3, &$1 TSRMLS_CC); }

Cela dit en gros, X > Y est équivalent à not X < Y ce qui est bien sûr faux lorsque la comparaison n'est pas commutative. Pensez à signaler ce problème sur bugs.php.net.

1voto

Artefacto Points 50896

Je ne dirais pas que le bug est dans $x > $y étant substitué à $y < $x .

Bien sûr, si vous avez mis en place $x > $y de manière à ce que les arguments ne changent pas de position lorsqu'ils sont transmis à la fonction de comparaison, vous résoudriez ce problème particulier. Mais vous en obtenez un autre en retour.

En ce moment, vous avez :

$x < $y <=> cmp($x, $y) == -1
$x > $y <=> cmp($y, $x) == -1

Parce que la première clé du premier argument est toujours comparée en premier, les deux conditions sont vraies si reset($x) < $y[key($x)] y reset($y) < $x[key($y)] .

Mais envisagez une autre mise en œuvre, qui résoudrait ce problème :

$x < $y <=> cmp($x, $y) == -1
$x > $y <=> cmp($x, $y) == +1

Maintenant < y > sont cohérents lorsque l'ordre des opérandes est fixe, mais nous obtenons maintenant un comportement bizarre lorsque nous intervertissons les opérandes car nous pourrions toujours avoir cmp($x, $y) == -1 y cmp($y, $x) == -1 ce qui signifie $x < $y y $y < $x seraient toutes deux vraies.

En somme, la seule solution serait de fixer la fonction de comparaison de façon à ce que son comportement soit antisymétrique, c'est-à-dire de façon à ce que cmp($x, $y) == - cmp($y, $x) au moins dans un ensemble d'éléments dont on affirme qu'ils sont comparables.

0voto

stefgosselin Points 5880

Je peux me tromper mais je ne pense pas que l'on puisse comparer des tableaux de cette façon. J'ai toujours supposé que l'on pouvait vérifier l'égalité ou l'inégalité, mais pas comparer des quantités avec < et >.

Le site page de manuel sur les opérateurs de tableau semble le confirmer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X