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

Comparing arrays in PHP - interesting behavior

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

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 the documentation at http://docs.php.net/manual/en/language.operators.comparison.php :

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

In our case, each key from the $ x array is present in the $ y array, so $ x and $ y are comparable. See also an example from the 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 behavior is really strange: $ x is less than $ y and at the same time $ x is greater than $ y (first example), and the two arrays are comparable.

I think this is because php is always compared, starting from one specific side of the '<' sign. I mean: for ($ x <$ y) php accepts $ x as operand 1, for ($ x> $ y) it accepts $ y as operand 1. Although I did not find anything like this in the documentation. <sh> What do you think of this?

+6
source share
3 answers

Your guess is correct. The > operator is parsed as

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

This basically means that X > Y equivalent to not X < Y , which, of course, is not true if the comparison is not commutative. Think about it at bugs.php.net.

+1
source

I would not say that the error in $x > $y is replaced with $y < $x .

Of course, if you implemented $x > $y in such a way that the arguments do not change their position when passing the comparison function, you would solve this problem. But you get more in return.

Now you have:

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

Since 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 that would solve this problem:

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

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

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

+1
source

Maybe I'm wrong, but I don't think you can compare arrays this way. I have always assumed that it is possible to verify equality or inequality, but not to compare values ​​with <and>.

the array operator man page seems to confirm this.

0
source

Source: https://habr.com/ru/post/891357/


All Articles