在 PHP 中比较数组 - 有趣的行为

发布于 2024-11-17 01:58:16 字数 1698 浏览 0 评论 0 原文

第一个示例:

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

结果:$xLessY = true,$xGreaterY = true

第二个示例:

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

结果:$ xLessY = false, $xGreaterY = false

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

如果操作数 1 中的键未在以下位置找到 操作数 2 那么数组是 无法比较,否则 - 比较 按价值计算

存在于数组 $y 中,因此 $x 和 $y 是可比较的。 另请参阅文档中的示例:

// 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。尽管我在文档中没有找到有关此行为的任何内容。
您对此有何看法?

The first example:

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

Result: $xLessY = true, $xGreaterY = true

The second example:

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

Result: $xLessY = false, $xGreaterY = false

According to documentation on http://docs.php.net/manual/en/language.operators.comparison.php:

if key from operand 1 is not found in
operand 2 then arrays are
uncomparable, otherwise - compare
value by value

In our case each key from array $x is present in array $y, so $x and $y are comparable.
See also the example from 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
}

This behaviour is really strange: $x is less than $y and at the same time $x is greater than $y (the first example) and two arrays are comparable.

I think this is because php always compares starting from the one definite side of sign '<'. I mean: for ($x < $y) php takes $x as operand 1, for ($x > $y) it takes $y as operand 1. Although I didn't find anything about this behaviour in documentation.
What are your thoughts on this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

南汐寒笙箫 2024-11-24 01:58:16

你的假设是正确的。 > 运算符被解析为

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

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

Your assumption is correct. The > operator is parsed as

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

This basically says, X > Y is equivalent to not X < Y, which is of course wrong when the comparison is not commutative. Consider reporting this on bugs.php.net.

眼眸里的快感 2024-11-24 01:58:16

我不会说这个错误是在 $x > 中。 $y 被替换为 $y $x

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

现在你有:

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

因为第一个参数的第一个键总是首先比较,所以如果 reset($x) reset($x) reset($x) reset($x) reset($x) reset($x) reset($x) $y[key($x)]reset($y) $x[键($y)]

但考虑另一种实现,它可以解决这个问题:

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

现在,当操作数的顺序固定时, <> 是一致的,但是当我们交换操作数,因为我们仍然可以有 cmp($x, $y) == -1cmp($y, $x) == -1,这将意思是 $x < $y$y < $x 都是 true。

总之,唯一的解决方案是修复比较函数,使其行为是反对称的,即 cmp($x, $y) == - cmp($y, $x),至少在一组声称具有可比性的元素中。

I wouldn't say the bug is in $x > $y being substituted for $y < $x.

Sure, if you implemented $x > $y in a way that the arguments did not exchange positions when passed to the comparison function, you would solve this particular problem. But you get another in return.

Right now you have:

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

Because the first key of the first argument is always compared first, both conditions are true if reset($x) < $y[key($x)] and reset($y) < $x[key($y)].

But consider another implementation, which would solve this problem:

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

Now < and > are consistent when the order of the operands is fixed, but we now get weird behavior when we swap the operands because we could still have cmp($x, $y) == -1 and cmp($y, $x) == -1, which would mean $x < $y and $y < $x would both be true.

In sum, the only solution would be to fix the comparison function so that its behavior was antisymmetric, i.e. so that cmp($x, $y) == - cmp($y, $x), at least within a set of elements that are claimed to be comparable.

装迷糊 2024-11-24 01:58:16

我可能是错的,但我认为你不能那样比较数组。我总是假设人们可以检查相等或不相等,但不能将数量与 << 进行比较。和>。

数组运算符的手册页似乎证实了这一点。

I may be wrong but I don't think you can compare arrays that way. I always assumed one can check for equality or inequality, but not compare quantities with < and >.

The man page on array operators seems to confirm this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文