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');
Related
I saw a small php quiz online that contained the following code:
$somevalue[[ 2 <=['-']=> 2][1]] = $somestring;
My question is, what does the part before the assignment do?
$somevalue[[ 2 <=['-']=> 2][1]]
<= looks like the comparison operator but in that case it is comparing 2 to '-'?
PHP's array initialization syntax looks like this:
$arr = [ key => value ];
So in this part:
2 <=['-']=> 2
The 'key' is the result of the expression 2 <= ['-'], which according to this page evaluates to true (an array is always greater than what you are comparing it to, unless it's another array). Because PHP arrays keys are either integers or strings, the boolean result is implicitly cast to the integer 1, so you end up with:
1 => 2
So the simplified expression:
[ 1 => 2 ][1]
Will evaluate to the second element of the array we've just created (PHP array's are 0-based), so this will simplify to:
2
So at the end we end up with:
$somevalue[2] = $somestring;
To understand this you need to break the statement in parts,
echo 2 <=['-'];//return true
PHP Comparison operator
After this the statement will be
$somevalue[[1 => 2][1]] = $somestring;
Here you see the array index 1 has values 2. After this the last index which is 1, from the array [1 => 2] it will return 2, so finally you will have
$somevalue[2] = $somestring;
In what ways can one determine whether the value of an array's index is falsey due to an out-of-bounds index in PHP?
For example, one might erroneously conclude that both $a and $b below have at least three items each, since the comparison of the third items in both arrays purport to have identical values at index 2, when in reality there is no index 2 in array $b. Indeed both values are null.
$a = array(1, false, null, 1, 0);
$b = array(true, 0);
echo (int)($a[0] === $b[0]); // 0
echo (int)($a[1] === $b[1]); // 0
echo (int)($a[2] === $b[2]); // 1 null<declared>===null<index-out-of-bounds>
echo (int)($a[3] === $b[3]); // 0
echo (int)($a[4] === $b[4]); // 0
Interesting question... Maybe somthing like this (but only for numeric array indexes):
(int)(count($a)>=$i && count($b)>=$i && $a[$i]===$b[$i])
?
EDIT: probably better solution based on array_key_exists:
(int)(array_key_exists($i, $a) && array_key_exists($i, $b) && $a[$i]===$b[$i] )
I have some issues with variables in php that i don't understand.
This is a simplified code example of the issue.
//Create an initial array with an sub-array
$a = array();
$a['test'] = array(1,2);
//Create an reference to $a['test'] in $b
//Changing $b[0] should now change the value in $a['test'][0]
$b = &$a['test'];
$b[0] = 3;
//Create an copy of $a into $c
$c = $a;
//Change one value in $c, which is an copy of $a.
//This should NOT change the original value of $a as it is a copy.
$c['test'][1] = 5;
print_r($a);
print_r($b);
print_r($c);
This is the output:
Array
(
[test] => Array
(
[0] => 3
[1] => 5
)
)
Array
(
[0] => 3
[1] => 5
)
Array
(
[test] => Array
(
[0] => 3
[1] => 5
)
)
The script creates an array with an sub-array and puts two values in it.
A reference to the sub-array is then put into b and one of the values in a is changed in this way.
I then make a copy of a into c.
I then change one value of c.
As c is a copy of a i would expect that the change on c did not affect a. But the output tells a different tale.
Can anyone explain why changing a value in the variable $c affect the value in $a when $c is just a copy of $a? Why is there a 5 in the values of $a?
You're assigning $b to $a by reference (that's what the & prefix does). Any changes to $b will effectively modify $a. Just force a declaration assignment:
$b = $a['test'];
$c does not modify $a. Here's the order of what's going on, and why the arrays are identical:
$a['test'] is assigned an array of 1,2.
$b is assigned as a reference to $a['test'], and modifies its values
$c is then assigned to $a, which has now been modified by $b.
I think i found the answer to my own question... On this page: http://www.php.net/manual/en/language.references.whatdo.php
I can't really understand why it does what it does. I do understand that i should probably avoid mixing references and arrays in the future.
Im refering to this section:
Note, however, that 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. Example:
<?php
/* Assignment of scalar variables */
$a = 1;
$b =& $a;
$c = $b;
$c = 7; //$c is not a reference; no change to $a or $b
/* Assignment of array variables */
$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) */
/* The contents of $arr are changed even though it's not a reference! */
?>
In other words, the reference behavior of arrays is defined in an
element-by-element basis; the reference behavior of individual
elements is dissociated from the reference status of the array
container.
You are passing the reference $a to $b by using $b = &$a['test']; Hence
change
$b = &$a['test'];
to
$b = $a['test'];
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)
I was trying to understand the in_array behavior at the next scenario:
$arr = array(2 => 'Bye', 52, 77, 3 => 'Hey');
var_dump(in_array(0, $arr));
The returned value of the in_array() is boolean true. As you can see there is no value equal to 0, so if can some one please help me understand why does the function return true?
This is a known issue, per the comments in the documentation. Consider the following examples:
in_array(0, array(42)); // FALSE
in_array(0, array('42')); // FALSE
in_array(0, array('Foo')); // TRUE
To avoid this, provide the third paramter, true, placing the comparison in strict mode which will not only compare values, but types as well:
var_dump(in_array(0, $arr, true));
Other work-arounds exist that don't necessitate every check being placed in strict-mode:
in_array($value, $my_array, empty($value) && $value !== '0');
But Why?
The reason behind all of this is likely string-to-number conversions. If we attempt to get a number from "Bye", we are given 0, which is the value we're asking to look-up.
echo intval("Bye"); // 0
To confirm this, we can use array_search to find the key that is associated with the matching value:
$arr = array(2 => 'Bye', 52, 77, 3 => 'Hey');
echo array_search(0, $arr);
In this, the returned key is 2, meaning 0 is being found in the conversion of Bye to an integer.
Try adding a third parameter true (strict mode) to your in_array call.
This is a result of the loose comparison and type juggling.
Loose comparison means that PHP is using == not === when comparing elements. == does not compare that the two variable types are equal, only their value, while === will ensure that they match in type and value (e.g. compare 0 == FALSE and 0 === FALSE).
So, basically, your in_array function is checking:
0 == 'Bye'
0 == 'Hey'
0 == 77
Note that the 52 will get lost due to the way you created your array.
So, note that if you do:
print (0 == 'Bye');
You will get 1. Apparently, PHP is type juggling the 'Bye' to 0, which is the same thing that will happen when you cast a string to an int, e.g. (int) 'string' will equal 0. Specific reference from the String conversion to numbers doc (Emphasis added):
The value is given by the initial portion of the string. If the string
starts with valid numeric data, this will be the value used.
Otherwise, the value will be 0 (zero). Valid numeric data is an
optional sign, followed by one or more digits (optionally containing a
decimal point), followed by an optional exponent. The exponent is an
'e' or 'E' followed by one or more digits.
Apparently, the integer type takes precedence over the string type (i.e. it could just as easily be doing the comparison by casting the int 0 to a string, which would then return False). This is specified in the comparison operators doc:
If you compare a number with a string or the comparison involves
numerical strings, then each string is converted to a number and the
comparison performed numerically.
Thanks for an interesting question that led me to do some research and learn something new!
in_array is supposed to be used on indexed arrays ([0], [1], [2] etc), not with a dictionary as you have defined (key-value store).
If you want to check if your array $arr includes '0', try using the PHP function array_key_exists instead - http://php.net/manual/en/function.array-key-exists.php.
var_dump(array_key_exists(0, $arr));
Type compare (third parameter) needs more system resources and more time.
Simply do that:
$x=0;
$result=in_array($x.'',array('ABC','BAC','12c','54'));
var_dump($result);