PHP equal variables - php

I wondered if there is any way to check if any of a large amount of variables are equal.
If I only have a few variables I can just do this:
if ($a == $b || $a == $c || $b == $c)
However, if I have 20 variables it will take some time to write all combinations. Is there another method?

if (count(array_unique(array($a, $b, $c), SORT_REGULAR)) === 1) {
// all equal
}
All this code does is place the variables in an array and eliminates duplicates. If they are all equal the result of array_unique() should be an array with one value.
If you want to make sure all of them are different it's not much different. Just check to see if the filtered array is the same size as the original array:
$array = array($a, $b, $c);
if (count(array_unique($array, SORT_REGULAR)) === count($array)) {
// all not equal
}

Related

Arrays not matching with strict comparison

$c1 = $v1 = array();
$v1['key'] = 'value';
echo '$c1 === $v1: ' . (($c1 === $v1) ? 'true' : 'false'); // prints false
$c1 === $v1 is false. But why? It seems that $v1 is automatically set to a different array then it's origin array automatically. Why it is happening?
Initially $c and $v1 is set to the same array instance. So if I mutate $v1 should not $c reflects the changes as they are set to the same array instance.
These will not be the same, because you explicitly set them to hold different values. The first is empty, while the second holds values.
They are not set to the same reference though, so they are two different variables - when you do
$c1 = $v1 = array();
You create two different arrays. If you want the change of one to reflect in both arrays, you need to make it a reference, by using the & operator in front of the variable identifier, like so.
$v1 = array();
$c1 = &$v1; // $c1 is now a reference to $v1
$v1['key'] = 'value';
echo '$c1 === $v1: ' . (($c1 === $v1) ? 'true' : 'false'); // true!
Notice that you need to reference it after the variable you wish to refer to has been made.
When using a reference like this, it goes both ways - any change to $v1 would be applied to $c1, and the other way around. So they are different variables, but will always hold the same values.
The comparison in the example above holds true because the arrays are exactly the same - not just by reference, but because they hold the same values and keys. If you compare two non-referenced arrays with the exact same values and exact same, matching keys, you would get a true equality too.
var_dump(array('foo') === array('bar')); // false; same keys, different values
var_dump(array('bar') === array('bar')); // true; same keys, same values
var_dump(array('bar') === array('baz' => 'bar')); // false; different keys, same value
Live demo
Passing variables by reference
Because they are two different object, with two different references, with happening one does not affect the other. Just simple like that.
Those arrays will not be the same because the second array has a value. Please run the following code:
<?php
$a = $b = [];
print_r($a);
print_r($b);
$result = ($a === $b) ? 1 : 0;
// The reasult will be 1 because the arrays are both empty.
print_r($result);
$b[0] = 'Ravi';
print_r($a);
print_r($b);
$result = ($a === $b) ? 1 : 0;
// The result will be 0 because the arrays are different.
print_r($result);

How to differentiate falsey array values from falsey out-of-bounds indices in php?

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] )

Help with user defined sort function

function sort_searches($a, $b)
{
return
(
(isset($b['Class_ID']) && !isset($a['Class_ID']))
||
($b['Results'] && !$a['Results'])
||
(is_array($a['Results']) && !$a['Results'] && !is_array($b['Results']))
);
}
I'm using this function in usort(). The intended effect is that a list of searches will be sorted first by whether they have Class_IDs, and then second by results (with a non-empty array of results > results === false > results === empty array(). So a sorted set of searches would look like:
Class_ID with results
Class_ID with results === false
Class_ID with results === array()
No Class_ID with results
No Class_ID with results === false
No Class_ID with results === array()
Currently the functions sorts on results completely fine, but not on whether a search has a Class_ID.
usort($searches, 'sort_searches')
From the PHP docs:
The comparison function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
Your function is not returning an integer.
To spell it out, let's say we wanted to write a sorting function for numbers (totally unnecessary, but for the exercise):
function sort_nums($a, $b)
{
if ($a < $b) return -1; // $a is less than $b
if ($a > $b) return 1; // $a is greater than $b
return 0; // $a is equal to $b
}

Compare the lengths arrays that have duplicates

I wish to determine whether there are any duplicates in two arrays, i.e. duplicates in array1 or duplicates in array2. If there are, then set a variable to equal 1, otherwise 0. I have the following code but it does not seem to work and I cannot understand why:
$a = count(array_unique($myarraydf));
$b = count($myarraydf);
$c = count(array_unique($myarrayds));
$d = count($myarrayds);
if (($a == $b) || ($c == $d)) {
$ties = 0;
}
else {
$ties = 1;
}
where $myarraydf and $myarrayds are arrays of numeric values.
If you want to set $ties = 1 if there are duplicates in either set, you need to change your operator to AND:
if (($a == $b) and ($c == $d)) {
If you want to set $ties = 1 if both contain duplicates, then the OR is correct.
I suggest using array_diff, see: http://us3.php.net/array_diff

PHP: Built-in function to check whether two Array values are equal ( Ignoring the order)

Is there a built-in function for PHP for me to check whether two arrays contain the same values ( order not important?).
For example, I want a function that returns me true for the following two inputs:
array('4','5','2')
array('2','4','5')
Edit: I could have sorted the two arrays and compare them, but as I am such a lazy guy, I would still prefer a one-liner that I can pull out and use.
array_diff looks like an option:
function array_equal($a1, $a2) {
return !array_diff($a1, $a2) && !array_diff($a2, $a1);
}
or as an oneliner in your code:
if(!array_diff($a1, $a2) && !array_diff($a2, $a1)) doSomething();
The best solution is to sort both array and then compare them:
$a = array('4','5','2');
$b = array('2','4','5');
sort($a);
sort($b);
var_dump($a === $b);
As a function:
function array_equal($a, $b, $strict=false) {
if (count($a) !== count($b)) {
return false;
}
sort($a);
sort($b);
return ($strict && $a === $b) || $a == $b;
}
Here’s another algorithm looking for each element of A if it’s in B:
function array_equal($a, $b, $strict=false) {
if (count($a) !== count($b)) {
return false;
}
foreach ($a as $val) {
$key = array_search($val, $b, $strict);
if ($key === false) {
return false;
}
unset($b[$key]);
}
return true;
}
But that has a complexity of O(n^2). So you better use the sorting method.
The array_diff() method above won't work.
php.net's manual says that array_diff() does this:
"Returns an array containing all the entries from array1 that are not present in any of the other arrays."
So the actual array_diff() method would be:
function array_equal($array1, $array2)
{
$diff1 = array_diff($array1, $array2);
$diff2 = array_diff($array2, $array1);
return
(
(count($diff1) === 0) &&
(count($diff2) === 0)
);
}
However I go with the sort method :D
You can use array_diff.
$a = array('4','5','2');
$b = array('2','4','5');
if(count(array_diff($a, $b)) == 0) {
// arrays contain the same elements
} else {
// arrays contain different elements
}
However, a problem with this approach is that arrays can contain duplicate elements, and still match.
You can use array_intersect() instead of array_diff():
$a = array('4','5','2');
$b = array('2','4','5');
$ca = count($a);
$cb = count($b);
$array_equal = ( $ca == $cb && $ca == count(array_intersect($a, $b)) );
Performance wise. solution, where two factors are important:
the more often arrays are matching, the more array_intersect() is fast.
the more arrays are big (more than 10 values), the more array_intersect() is fast.
Depending on these factors, one method can be two or three time faster than the other. For big arrays with few (or no) matching combinations, or for little arrays with lots of matching, both methods are equivalent.
However, the sort method is always faster, except in the case with little arrays with few or no matching combinations. In this case the array_diff() method is 30% faster.
You only need to compare one-way using array_diff() and use count() for the inverted relationship.
if (count($a1) == count($a2) && !array_diff($a1, $a2)) {
// equal arrays
}
If the arrays being compared consist of only strings and/or integers, array_count_values allows you to compare the arrays quickly (in O(n) time vs O(n log n) for sorting) by verifying that both arrays contain the same values and that each value occurs the same # of times in both arrays.
if(array_count_values($a1) == array_count_values($a2)) {
//arrays are equal
}
As an addition to the accepted reply from #knittl
To cover the case, when one of the arrays has additional members:
function areEqualIfOrderIgnored(array $a1, array $a2): bool
{
if (
! array_diff($a1, $a2)
&& ! array_diff($a2, $a1)
&& count($a1) === count($a2)
) {
return true;
}
return false;
}
Or one line, as requested (but not nice)
if (! array_diff($a1, $a2) && ! array_diff($a2, $a1) && count($a1) === count($a2)) {do smth}

Categories