Opposite of array_intersect - php

I'm looking for the opposite of the function array_intersect, basically a function that returns the element that are not present in each of the provided arrays.
Example:
$a1 = array(1, 2, 3);
$a2 = array(2, 3, 4);
$result = array(1, 4);
I know how to do it programmatically (I just have two array so array_merge(array_diff($a1, $a2), array_diff($a2, $a1)) would do the job), but I'd like to know whether there's a built-in function that I can't find.
Thanks.

Since array_diff($a, $b) !== array_diff($b, $a)
the inverse of array_intersect is:
array_merge(array_diff($a,$b), array_diff($b,$a));
Here it is in a PHPUnit test format:
class ArrayInverseTest {
function testInverseArrayIntersect() {
$a = array(1, 2, 3);
$b = array(2, 3, 4);
$this->assertEquals(
array_values(array(1, 4)),
array_values(array_merge(array_diff($a, $b), array_diff($b, $a)))
);
}
}

It's not built in. Note that you can improve your solution:
array_merge($a1, array_diff($a2, $a1));

No there isn't builtin for that
I believe a language will never provide such a builtin function

Are you looking for array union? http://es.php.net/manual/en/language.operators.array.php

Related

PHP array_intersect() till the first match

I have 2 arrays to compare and find if there is at least a single value in common.
This works just fine:
$arr1 = array(1, 2, 3, 4, 5);
$arr2 = array(2, 3, 4, 5, 6);
if (array_intersect($arr1, $arr2)) {
// good, at least one match found
}
However, the question is performance. It doesn't make sense to continue looping thru the arrays after the first match was found. Is there a native PHP function or a useful snippet to achieve this?
Will a combination of foreach() and in_array() do the trick?
How about this?
foreach ($arr1 as $key => $val) {
if (in_array($val, $arr2)){
// do something, maybe return so you wouldn't need break
break;
}
}
Just compare the first value?
$arr1 = array(1, 2, 3, 4, 5);
$arr2 = array(2, 3, 4, 5, 6);
if (array_intersect($arr1, $arr2)[0]) {
// good, at least one match found
}

Finding the index of an object in an array when there are multiple possibilities

I have an array, and I want to find all of the indexes of a certain object in the array. When I use array_search, it only returns the first index in which the object can be found.
echo array_search(3, array(3, 3, 4));
This returns 0, but I want to know that both indexes 0 and 1 have the integer 3 as their object. Is there a way of doing this without using a for loop?
Try array_keys() method :
$array = array(3, 3, 4);
print_r(array_keys($array, "3"));
For reference:
array_keys() — Return all the keys or a subset of the keys of an array Info & usuage examples : http://php.net/manual/en/function.array-keys.php
As an alternative to array_keys, array_filter() retains associativity
$key = 3;
$array = array(1, 3, 3, 4, 3, 5);
$result = array_filter(
$array,
function ($item) use ($key) {
return ($item == $key);
}
);
var_dump($result);

Compare two arrays, is there common elements between the two arrays?

I need to test if one element of an array is in another array.
$array_one = array("gogo", "blabla", "toto");
$array_two = array("stackov", "renaul", "toto");
I would like to know if one element of array_one is in array_two ???
How to test that? Am trying in_array but it seems to have problems.
array_intersect()
$array1 = array("gogo", "blabla", "toto");
$array2 = array("stackov","renaul","toto");
$commonElements = array_intersect($array1,$array2);
var_dump($commonElements);
Try this one:
array_intersect($array_one, $array_two);
Mark's answer should be enough for your problem.
If you ever wish to find the intersect of more than 2 arrays, use this:
$arrays = array(
array(1, 2, 3),
array(2, 4, 6),
array(2, 8, 16)
);
$intersection = call_user_func_array('array_intersect', $arrays);

Callback function using variables calculated outside of it

Basically I'd like to do something like this:
$arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
$avg = array_sum($arr) / count($arr);
$callback = function($val){ return $val < $avg };
return array_filter($arr, $callback);
Is this actually possible? Calculating a variable outside of the anonymous function and using it inside?
You can use the use keyword to inherit variables from the parent scope. In your example, you could do the following:
$callback = function($val) use ($avg) { return $val < $avg; };
For more information, see the manual page on anonymous functions.
If you're running PHP 7.4 or later, arrow functions can be used. Arrow functions are an alternative, more concise way of defining anonymous functions, which automatically capture outside variables, eliminating the need for use:
$callback = fn($val) => $val < $avg;
Given how concise arrow functions are, you can reasonably write them directly within the array_filter call:
return array_filter($arr, fn($val) => $val < $avg);
use global variables i.e $GLOBAL['avg']
$arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
$GLOBALS['avg'] = array_sum($arr) / count($arr);
$callback = function($val){ return $val < $GLOBALS['avg'] };
$return array_filter($arr, $callback);

What's the most elegant way to add up multidimensional arrays field by field in PHP?

I'm trying to add up two multidimensional arrays, both equally sized, field by field. I.e.:
$sum[4][3] = $a[4][3] + $b[4][3];
Or:
$a = array( array(1, 4), array(3, 2));
$b = array( array(9, 2), array(1, 0));
Should result in:
$sum = array( array(10, 6), array(4, 2));
Is there a more elegant way than foreaching over all the arrays?
You can use the function array_map() This applies a function to each of the elements in an array ($a in your case) and applies a callback function to those, you can give extra arguments to those functions by supplying another array ($b in your case). The result will be $sum of your example.
The callback function would need to check if the arguments are arrays, if so it would need to do the mapping function again (so its a recursive function) if the arguments aren't an array it needs to add the function.
http://nl3.php.net/manual/en/function.array-map.php
So all in all you'd be off much better doing a nested foreach :)

Categories