2011-06-25 25 views
6

第一个例子:比较阵列 - 有趣的行为

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

结果:$ xLessY = 真正,$ xGreaterY = 真正

第二个例子:

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

结果:$ xLessY = ,$ xGreaterY =

http://docs.php.net/manual/en/language.operators.comparison.php根据文档:

如果从操作数1钥匙没有 操作数2,则发现阵列是 不可比否则, - 比较 按值计算

在我们的例子中,数组$ x中的每个键都存在于数组$ y中,所以$ x和$ y是comp耕地。 参见例如,从文档:

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

这种行为是非常奇怪的:$ x小于$ y和在同一时间$ x大于$ Y(第一个例子)和两个数组具有可比性更大。

我认为这是因为PHP总是从符号'<'的一个确定的一边开始比较。我的意思是:for($ x < $ y)php以$ x作为操作数1,对于($ x> $ y)它需要$ y作为操作数1.尽管我在文档中没有找到有关此行为的任何信息。
你对此有何看法?

+0

我怀疑你可能是正确的,无论哪个值在'<'的最尖端被用作第一个操作数。当然,如果你看看PHP源代码,你可以找到答案... – 2011-06-25 20:42:51

回答

0

我可能是错的,但我不认为你可以用这种方式比较数组。我总是假定可以检查平等或不平等,但不能将数量与<和>进行比较。

man page on array operators似乎证实了这一点。

+0

还有[另一个手册页](http://php.net/manual/en/language.operators.comparison.php) 。参见下表“与各种类型的比较”和下面的文本:“如果在操作数2中没有找到操作数1的密钥,那么数组中的元素较少,否则 - 按值比较值(请参见以下示例)” 。还有我写的example(standard_array_compare函数) – Andy

1

你的假设是正确的。该>操作被解析为

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

这基本上说,X > Y相当于not X < Y,这当然是错误的,当比较是不可交换的。考虑在bugs.php.net上报告这一点。

+0

可交换? 'X> Y'是可交换的,意味着''X> Y''等价于'Y> X'。另外,你说“比较(比较btw)不可交换”暗示'X> Y'不等于'不是X Y'相当于'不是X $ y'和'$ y> $ x'对于' $ x!= $ y'。 – Artefacto

+0

我同意没有明智的方法来排序关联数组,但这并不意味着设置一些任意顺序是没有用的 - 例如,许多算法依赖于正在排序的数据。然而,目前的情况是,不仅在数组宇宙中没有总顺序,而且手工状态下有明确定义的顺序的数组在'<' and '>'之间实际上并不一致。 – Artefacto

1

我不会说这个bug是$x > $y$y < $x所取代。

当然,如果你实现了$x > $y这种方式,参数在传递给比较函数时没有交换位置,你可以解决这个问题。但你得到另一个回报。

现在您有:

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

因为第一个参数的第一密钥总是首先比较,两个条件都为真,如果reset($x) < $y[key($x)]reset($y) < $x[key($y)]

但考虑另一种实现方式,这将解决这个问题:

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

现在<>当操作数的顺序是固定的是一致的,但我们现在得到怪异的行为,当我们交换操作数,因为我们仍然可以有cmp($x, $y) == -1cmp($y, $x) == -1,这意味着$x < $y$y < $x都是正确的。

总而言之,唯一的解决方案是修正比较函数,使其行为是反对称的,即至少在声称可比的一组元素内。

+0

我认为这种行为'$ x <$ y == -1'和'$ y <$ x == -1'在无序数组的情况下更容易理解。这与文档更加一致。 – Andy

+0

也许这不是一个错误,但他们应该记录它 – Andy