I want to do the intersection between two multidimensional arrays in php 5. E.g:
$a = array(array(), array(1), array(2));
$b = array(array(), array(0), array(2));
I naturally try:
array_intersect($a, $b)
But it gives me Notice because of array to string conversion. As a workaround, I want to precise the comparison function using uintersect:
array_uintersect($a, $b, function($x, $y){return $x == $y ? 0 : ( $x < $y ? -1 : 1 );})
And it works. But this is kind of ugly. My question is simple, is there a built-in natural comparison function which works on array and which I could use as callback function like in:
array_uintersect($a, $b, 'natcmp')
Thank you!
Consider the below code in PHP
$a = 8425996523 * 121212713;
$b = sprintf('%.2f', $a);
$mul = gmp_mul("8425996523", "121212713");
Output is
1.0213378982814E+18
1021337898281396864.00
1021337898281396899
The actual answer is 1021337898281396899. Hence, it is clear that we need to use any libraries like gmp_mul to do arithmetic with large numbers.
My question is, how to identify such errors?
ie, when PHP does a calculation like
8425996523 * 121212713
, how can I identify that the result is not correct?
One way I see is to check for E and assume that whenever we forcefully convert such numbers, the errors exits.
Use
$b = sprintf('%.2d', $a);
Instead of
$b = sprintf('%.2f', $a);
Here's a screenshot of the source code to show the difference:
So when I try the following:
$a = '1.00';
$b = '1.01';
if($a < $b){
print 'ok';
}
This works fine. But when I retrieve these variables from an xml file. the strings are EXACTLY the same, but for some reason, the if function doesn't work right. So I assume I have to convert the strings to a number. But when I do so, the decimals get removed.
Is my assumption correct? If so, how do i solve it?
If not, what's the problem?
Thank you!
$a = (float) $a;
$b = (float) $b;
Related reading: http://php.net/manual/en/language.types.type-juggling.php
Found the answer by googling :)
floatval($string);
I have 2 arrays like those:
$a = array(152,32,113,47,53);
$b = array("a","w","lk","qw","ol");
I will sort $a by using asort() and I want to auto-sort the second array $b likewise $a.
How to do I?
You can use array_multisort.
http://us2.php.net/manual/en/function.array-multisort.php
I want to know how to array_intersect for object array.
You can use array_uintersect in conjunction with spl_object_hash, see an example:
array_uintersect($a, $b, function($a, $b) {
return strcmp(spl_object_hash($a), spl_object_hash($b));
});
where '$a' and '$b' are arrays of some objects that you want to intersect.
nice toString function is already implemented and is called serialize ;) so
array_map(
'unserialize',
array_intersect(
array_map(
'serialize',
$obj1
),
array_map(
'serialize',
$obj2
)
)
);
will do the work, example mentioned higher don't work 'cause array_intersect work's only with strings as someone mentioned too
array_intersect() returns an array containing all the values of array1 that are present in all the arguments.
Then what mean present in this context (exacly this function), i found on php.net my answer:
Two elements are considered equal if
and only if (string) $elem1 ===
(string) $elem2. In words: when the
string representation is the
same.
Then you can't use it on array of objects if your objects not implements unique conversion to string.
Had a similar problem a few days ago, while these are answers are on the right path; I used them to work out the following:
From Artefacto's answer return $obj1 == $obj2 didn't really work, so I wrote a simple comparative function (basically gets the md5 of the serialised object and compares that):
function object_compare($obj1, $obj2){
$md5 = function($obj){
return md5(serialize($obj));
};
return strcmp($md5($obj1), $md5($obj2));
}
Then it’s jut a matter of calling array_uintersect with our comparative function to get the intersection:
# $array1 / $array2 are the array of objects we want to compare
return array_uintersect($array1, $array2, 'object_compare');
In my case, I had an unknown / dynamic array of objects, so I took it a step further so I don't have to declare array_uintersect($array1, $array2, ...) specifically - but just be able to pass in an array of arrays (of objects):
# $multiarray_of_objects is our array of arrays
$multiarray_of_objects[] = 'object_compare';
return call_user_func_array('array_uintersect', $multiarray_of_objects);
Just gotta remember to pass in the reference to our callback / comparative function as the last string in the array. Works like a charm!
The correct way to check whether two objects are equal is to use ==. Therefore:
array_uintersect($arr1, $arr2, function ($a1, $a2) { return $a1 == $a2; });
Just for completeness: Implement __toString() method in your object returning a unique value. For database entities this might be as easy as returning the fully qualified class name postfixed with the ID of the record. But it can also be arbitrarily complex by doing some hashing or even worse things.
In my opinion, it's the class's duty to serialize itself or create something unique to compare its objects by. Using anything outside of a class to serialize an object might result in strange behaviour (including comparing objects of different classes, which must never result in equality).
I use array_udiff to implement array_intersect for an object array.
function diff($a, $b) {
if($a === $b) {
return 0;
} else {
return 1;}
}
$array_1 = array('a', 'b', 'c');
$array_2 = array('c', 'd','e');
$array = array_udiff($array_1, array_udiff($array_1, $array_2, 'diff'),'diff');
var_dump($array);
return array(1) { [2]=> string(1) "c" }
You can have your own diff function for any scheme.
The correct solution would be:
array_uintersect($arr1, $arr2, function ($a1, $a2) { return $a1 != $a2; });
Note the != in the callback function as opposed to the answer from #Artefacto. Based on the documentation of array_uintersect, the callback function has to return 0 (false) if array items are equal.