Difference between == and === WRT arrays in php? - php

I'm reading about php and it says,
== is Equality such that $a == $b is true if $a and $b have the same elements.
=== is Identity such that $a === $b is true if $a and $b have the same elements, with the same types, in the same order.
So, I thought I'd try and see the difference myself and wrote with this little script:
$a = array(1, 2, 3);
$b = array(2, 3, 1);
if ($a==$b) {echo "yeehaw!";} else {echo "nope";}
if ($a===$b) {echo "yup";} else {echo "nope";}
My thought was that the same order wasn't required for two arrays to be equal. However, when I ran this, I got "nope" and "nope".
What is the difference?

The arrays you've provided have the same set of values, but different key-value-pairs.
Try the following use case instead (same key-value-pairs in different order):
$a = array(0=>1, 1=>2, 2=>3);
$b = array(1=>2, 2=>3, 0=>1);
... and the following use case (different data types):
$a = array(1, 2, 3);
$b = array('1', '2', '3');

The documentation[PHP.net] says:
== TRUE if $a and $b have the same key/value pairs.
=== TRUE if $a and $b have the same key/value pairs in the same order and of the same types.
Since your two arrays are not in the same order1, they don't have the same key-value pairs.
var_dump($a);
array(3) {
[0]=> int(1)
[1]=> int(2)
[2]=> int(3)
}
var_dump($b);
array(3) {
[0]=> int(2)
[1]=> int(3)
[2]=> int(1)
}
1 With regards to their construction via array(), which will index the arguments starting with 0.

My thought was that the same order wasn't required for two arrays to be equal.
To make it clear what the documentation meant by same key/value pairs, let's take a look at the actual array contents:
$a = array(
0 => 1,
1 => 2,
2 => 3,
);
$b = array(
0 => 2,
1 => 3,
2 => 1,
);
Clearly, the pairs are different.
So what about that "same order"?
To illustrate that, let's create $b a little different:
$b => array(
2 => 3,
1 => 2,
0 => 1,
);
The == equality will be satisfied because the pairs are now the same. However, because arrays in PHP are ordered maps, a difference in pair order causes the === equality to fail.

Two arrays are considered identical === if:
number of elements is the same
all data types are the same
all elements are in the same order
each array has the same key-value pairs

What is the difference?
The difference between two arrays can mean different things, so this question is normally best answered by using the kind of difference function for arrays that match your expectations.
In your case, equality is (probably) satisfied by the array_diff() function:
!array_diff($a, $b) && !array_diff($b, $a);
If you say no, that's not what I'm looking for, please see the duplicate question "PHP - Check if two arrays are equal" I also left an extended answer there that shows the other possible differences and how to test for those as you're concerned about comparing values and not element (which are key/value pairs).

1st one fails because the elements are different. 2nd one fails because elements are different although type is same. (both should same)

Related

Does PHP's array equality require elements in the same order?

According to http://php.net/manual/en/language.operators.array.php:
$a == $b Equality TRUE if $a and $b have the same key/value pairs.
$a === $b Identity TRUE if $a and $b have the same key/value pairs in the same order and of the same types.
As such, I would have expected these two arrays to have equality, but they do not.
$a1=array('a','b');
$a2=array('b','a');
echo(($a1==$a2)?'equal':'not equal');
I could sort the arrays first and they have both equality and identity.
Am I misinterpreting the PHP manual? Does PHP's array equality require elements in the same order?
EDIT. The posted answers perfectly answered the question. Possible workarounds include the following. While not part of my original question, any recommendations on the best way to implement would be appreciated.
<?php
$a1=array('a','b');
$a2=array('b','a');
echo((($a1==$a2)?'equal':'not equal').'<br>');
echo(((array_diff($a1, $a2) === array_diff($a2, $a1))?'equal':'not equal').'<br>');
sort($a1);
sort($a2);
echo((($a1==$a2)?'equal':'not equal').'<br>');
?>
OUTPUT:
not equal
equal
equal
That's Because:
In the first array it's:
0 => a
1 => b
And in the second array it's:
0 => b
1 => a
So the values and the keys are the same, but not as pair!
So if you change the keys in the second array it's TRUE because the value and the key's are the same as pair:
$a1 = array('a','b');
$a2 = array( 1 =>'b', 0 =>'a');
echo(($a1==$a2)?'equal':'not equal');
Output:
equal
Its a good question but as the docs mention. It needs the same key value pairs. Your first array is 1 => a and your second is 2=>a
Same for b. So therefore not equal.
An example would be
$a=array('a'=>'a','b'=>'b');
$a=array('b=>'b','a'=>'a');

Arrays and references in PHP

Today I was reading article What Reference Do from PHP's official manual page and found the following piece of code:
<?php
$arr = array(1);
$a =& $arr[0]; //$a and $arr[0] are in the same reference set
$arr2 = $arr; //not an assignment-by-reference!
$arr2[0]++;
/* $a == 2, $arr == array(2) */
And that what manual says about this code:
References inside arrays are potentially dangerous. Doing a normal
(not by reference) assignment with a reference on the right side does
not turn the left side into a reference, but references inside arrays
are preserved in these normal assignments. This also applies to
function calls where the array is passed by value.
Can someone explain me why after execution of the code we will have $a and $arr equal to 2 ?
Perhaps this will make it clearer:
$arr = array(1,1);
$a =& $arr[0]; //$a and $arr[0] are in the same reference set
$arr2 = $arr; //not an assignment-by-reference!
$arr2[0]++;
$arr2[1]++;
/* $a == 2, $arr == array(2) */
var_dump($arr);
//outputs array(2) { [0]=> &int(2) [1]=> int(1) }
The reason the value is incremented is because the reference inside the array is preserved in the normal assignment. $arr2[0], $arr[0] and $a now all refer to the same value, even though $arr2 is a copy of $arr. Note how $arr2[1]++ does not increment $arr[1].
Do a var_dump($arr); and you'll see the issue. $arr[0] will have an &int type.
This means $arr[0] becomes a reference to a value.
And the $arr array will actually have a reference as its first value.
When you duplicate the array, the reference is carried over as the first element will keep being a reference and will still modify the referenced value.
It's an array thing. Seems really weird but once you understand it, it makes sense... as much as PHP makes sense :)
PS: This behavior is why call_user_func_array() can take an array() of references as it's argument and allows you to call functions that accept reference arguments.

Can anyone explain how uksort() in PHP works?

I have read about uksort in the PHP manual but it is very difficult to understand.
Can any one help me out?
Here is an example:
<?php
function my_sort($x, $y)
{
if ($x == $y) return 0;
return ($x > $y) ? -1 : 1;
}
$people = array(
"10" => "javascript",
"20" => "php", "60" => "vbscript",
"40" => "jsp");
uksort($people, "my_sort");
print_r($people);
?>
What is happening here?
As said in the manual, your function (my_sort in this case) should return:
a negative integer (in this case -1) if you consider $a to be less than $b
a positive integer if you consider $a to be greater than $b
0 if you consider them to be the same.
As you may have guessed, uksort will use your comparison function to see in which order the elements should be in the sorted array. It will call your function multiple times, every time with two keys. You compare those to keys to each other and give your result back.
The idea is that you can program your own comparison function which does something non-trivial, for example if you want a certain key to always be first. Your trivial example can use the regular krsort instead.

int to string on array - suggestions for this context

I have these arrays : $_POST['atlOriginal'] and $oldAtlPos. The values stored of both are this :
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
Now, if I done this comparison $_POST['atlOriginal']===$oldAtlPos it returns false, because $_POST['atlOriginal'] values are Strings (the are passed trought GET/POST from client) and $oldAtlPos values are Integer.
What can I do here? What's the best strategy? Convert one in another?
P.S. I need to valutate the order of the values, so === is necessary;
P.S. 2 Values of Both will be stored in the database as Char(2);
EDIT
So :
for($i=0; $i<sizeof($oldAtlPos); $i++) echo $_POST['atlOriginal'][$i]."|".gettype($_POST['atlOriginal'][$i])." - ".$oldAtlPos[$i]."|".gettype((string)$oldAtlPos[$i])."<br/>";
will return :
0|string - 0|string
1|string - 1|string
2|string - 2|string
3|string - 3|string
4|string - 4|string
5|string - 5|string
6|string - 6|string
7|string - 7|string
8|string - 8|string
9|string - 9|string
10|string - 10|string
11|string - 11|string
12|string - 12|string
13|string - 13|string
14|string - 14|string
15|string - 15|string
16|string - 16|string
17|string - 17|string
18|string - 18|string
But seems that if($_POST['atlOriginal']===(string)$oldAtlPos) still return false...
Do not compare values with their types using ===.
Compare just only values using ==.
Edit:
For example, there are:
$a = array(1, 2, 3);
$b = array('1', '2', '3');
and then when you compare those arrays in 2 ways (== and ===), you will get following results:
$a == $b; // TRUE
$a === $b; // FALSE
So as you can see, what you need is to use == compare method.
Edit 2:
In your P.S. you say that you need to compare arrays order too.
It does it already. If you compare arrays like that you will get false:
$a = array(3, 2, 1);
$b = array('1', '2', '3');
$a == $b; // FALSE
If you are trying to compare them you could:
use == instead of === (recommended)
== means 'do these values match'
=== means 'do these values match and are they of the same type'
$foo['test'] = Array("1","2","3");
$bar = Array(1,2,3);
$baz = Array(3,2,1);
var_dump($foo['test'] === $bar); // FALSE - does not work
var_dump($foo['test'] === (string) $bar); // FALSE - does not work
var_dump($foo['test'] == $bar); // TRUE - works!
var_dump($foo['test'] == $baz); // FALSE - works because $baz is in a different order
== does not check key/value pair order however since you are only using values, the key is essentially the order and matches (so this does what you want)
From this above code, this is what the array actually looks like
$foo['test']
array(3) {
[0]=>
string(1) "1"
[1]=>
string(1) "2"
[2]=>
string(1) "3"
}
$bar
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
== checks to make sure the key (the part in []) and value (int() in this case) match, it does not check order -- but this does not matter since you are only using values and the key is the order.
The only time this would affect you is if you were using key/value pairs and wanted to check order such as:
// key/value pairs match but order does not
Array('1' => 'B', '0' => 'A') === Array('0' => 'A', '1' = 'B') // FALSE
Array('1' => 'B', '0' => 'A') == Array('0' => 'A', '1' = 'B') // TRUE -- order is not checked
Fix: If you are using Key=>Value pairs then this will do the trick:
// Function to fix data
function array_fix(&$item, $key)
{
$item = intval($item);
}
$foo['test'] = Array(1=>"1",2=>"2",3=>"3");
$bar = Array(1=>1,2=>2,3=>3);
$baz = Array(2=>2,1=>1,3=>3);
// str !== int
var_dump($foo['test'] === $bar); // FALSE
// Apply fix to all data in array
array_walk($foo['test'],'array_fix');
// int === int -- yay :-D
var_dump($foo['test'] === $bar); // TRUE
var_dump($foo['test'] === $baz); // FALSE - correct: out of order
you have to iterate though each elements and compare them individually

How does the equivalence operator work with arrays in PHP?

Code:
$arr = array( 10, 20, 30 );
$arr1 = array(
1=>30,
2=>20,
0=>10
);
var_dump( $arr == $arr1 );
$a = array( 1, 2, 3);
$b = array(
1=>2,
2=>3,
0=>1
);
var_dump($a == $b);
This outputs:
bool(false)
bool(true)
Two arrays will be considered equal if their corresponding values are the same.
In your first example you are comparing two arrays:
[10, 20, 30]
[10, 30, 20]
Obviously these are not the same, so it returns false. The second example though:
[1, 2, 3]
[1, 2, 3]
...are the same. Am I missing something here?
If you want to test if two arrays have the same members, see this question:
Algorithm to tell if two arrays have identical members
If you just want to see they have the same totals, you can use array_sum
If you do not specify keys for array, php automatically selects numbers, starting with 0.
Therefore, the following pairs of lines mean the same:
$arr = array(10,20,30);
$arr = array(0=>10,1=>20,2=>30);
$a = array(1,2,3);
$a = array(0=>1,1=>2,2=>3);
It's to be expected, that
array(10,20,30) != array(10,30,20)
and
array(1,2,3) == array(1,2,3)
Given some of your comments, I think it would be useful if you read up on array type in php. Mainly the fact that there is no key-less arrays.
And don't forget comparison operators as well.
Thats a very broad question, but in the case of an array, it compares on an index-by-index basis.
In your first block of code, $arr is not equal to $arr1 because 30 != 10 and 10!=30.
In the second block of code, you are specifying that at index 0, the value is 1. At index 1, the value is 2, and at index 2, the value is 3. Thus, you have the same array.
th equality operator is === in php and within an array => is correct. also $arr !=$arr1 coz 20 !=30, 30!=20 as per you have assigned.

Categories