2011-06-25 10 views
6

El primer ejemplo:matrices que comparan en PHP - comportamiento interesante

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

Resultado: $ xLessY = cierto, $ xGreaterY = cierto

El segundo ejemplo:

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

Resultado: $ xLessY = falsa, $ xGreaterY = falsa

De acuerdo con la documentación sobre http://docs.php.net/manual/en/language.operators.comparison.php:

si la clave del operando 1 no se encuentra en operando 2 a continuación, las matrices son incomparable de lo contrario, - comparar valor por valor

en nuestro caso cada tecla del array $ x está presente en matriz $ y, por lo $ x $ y y son los cultivable. Véase también el ejemplo de la documentación:

// 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 
} 

Este comportamiento es muy extraño: $ x es menor que $ yy al mismo tiempo, $ x es mayor que $ y (el primer ejemplo), y dos conjuntos son comparables .

Creo que esto es porque php siempre se compara comenzando desde el lado definido del signo '<'. Quiero decir: para ($ x < $ y) php toma $ x como operando 1, para ($ x> $ y) lleva $ y como operando 1. Aunque no encontré nada sobre este comportamiento en la documentación.
¿Qué piensas sobre esto?

+0

Sospecho que es posible que tenga razón acerca de cómo se usa el primer valor en el extremo puntiagudo de '<' como primer operando. Por supuesto, puede encontrar la respuesta con seguridad si mira el código fuente de PHP ... –

Respuesta

0

Puedo estar equivocado, pero no creo que pueda comparar matrices de esa manera. Siempre he asumido que se puede verificar la igualdad o la desigualdad, pero no comparar cantidades con < y>.

El man page on array operators parece confirmar esto.

+0

Hay [otra página de manual] (http://php.net/manual/en/language.operators.comparison.php) . Consulte la tabla "Comparación con varios tipos" y el siguiente texto: "La matriz con menos miembros es más pequeña, si la clave del operando 1 no se encuentra en el operando 2, las matrices son incomparables; de lo contrario, compare el valor por valor (consulte el siguiente ejemplo)" . Y también está el ejemplo (función standard_array_compare) que escribí – Andy

1

Su suposición es correcta. El operador > se analiza como

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

Esto básicamente dice, X > Y es equivalente a not X < Y, que por supuesto es incorrecto cuando la comparación no es conmutativa. Considera reportar esto en bugs.php.net.

+0

¿conmutativa? 'X> Y' siendo conmutativo significa que' X> Y' es equivalente a 'Y> X'. Además, dices "la comparación (que por comparación btw) no es conmutativa" implica que "X> Y" no es equivalente a "no X Y 'es equivalente a' no X $ y' y' $ y> $ x' son verdaderos con ' $ x! = $ y'. – Artefacto

+0

Acepto que no existe una forma sensata de ordenar matrices asociativas, pero esto no significa que tener una configuración de orden arbitraria no sea útil; por ejemplo, muchos algoritmos dependen de los datos que se solicitan. Sin embargo, el estado actual de las cosas es que no solo no hay un orden total en el universo de matrices, sino que las matrices para las cuales el manual indica que hay un orden bien definido no tienen consistencia entre '<' and '>'. – Artefacto

1

No diría que el error está en $x > $y siendo sustituido por $y < $x.

Claro, si ha implementado $x > $y de una manera que los argumentos no intercambiaron posiciones cuando se pasa a la función de comparación, se podría resolver este problema en particular. Pero obtienes otro a cambio.

Ahora usted tiene:

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

Debido a que la primera clave del primer argumento siempre se compara en primer lugar, ambas condiciones son verdaderas si reset($x) < $y[key($x)] y reset($y) < $x[key($y)].

Pero considere otra implementación, lo que resolvería este problema:

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

ahora < y > son consistentes cuando el orden de los operandos es fija, pero ahora obtenemos un comportamiento extraño cuando intercambiamos los operandos porque aún podría tener cmp($x, $y) == -1 y cmp($y, $x) == -1, lo que significaría que $x < $y y $y < $x serían verdaderos.

En resumen, la única solución sería corregir la función de comparación de modo que su comportamiento fuera antisimétrico, es decir, cmp($x, $y) == - cmp($y, $x), al menos dentro de un conjunto de elementos que se afirma que son comparables.

+0

Creo que este comportamiento '$ x <$ y == -1' y' $ y <$ x == -1' es más comprensible en caso de matrices no ordenadas. Y esto es más consistente con la documentación. – Andy

+0

Quizás esto no sea un error, pero deberían documentar eso – Andy