Reputation: 349
I have 2 arrays that look like this:
$array1 = [
['id' => '434b5g6', 'unique_id' => 'banana', 'level' => 8],
['id' => 'bfrfnr', 'unique_id' => 'apple', 'level' => 4],
['id' => 'yt347509', 'unique_id' => 'grapefruit', 'level' => 9],
['id' => '456645', 'unique_id' => 'strawberry', 'level' => 1],
];
$array2 = [
['id' => 'gon235g6', 'unique_id' => 'strawberry', 'level' => 8],
['id' => 'bfrfnr', 'unique_id' => 'apple', 'level' => 4],
['id' => 'logujtng9', 'unique_id' => 'grapefruit', 'level' => 6],
['id' => '07yburhg', 'unique_id' => 'pinapple', 'level' => 1],
];
I need a way to remove the rows containing the same unique_id
value in both arrays so that I'm left with 2 arrays which only contain elements that do not exist in the other.
Desired results as two separate arrays:
[['id' => '434b5g6', 'unique_id' => 'banana', 'level' => 8]]
and
[['id' => '07yburhg', 'unique_id' => 'pinapple', 'level' => 1]]
I know there is array_diff()
, but this only works for single level arrays. I'm using multi-level arrays and only targeting the unique_id
column for comparisons.
Upvotes: 0
Views: 342
Reputation: 47992
array_udiff()
will directly return what you need with no data preparation at all.
Declare the columns to be compared in the custom callback function.
Code: (Demo)
// unique in $array1
var_export(array_udiff($array1, $array2, fn($a, $b) => $a['unique_id'] <=> $b['unique_id']));
// unique in $array2
var_export(array_udiff($array2, $array1, fn($a, $b) => $a['unique_id'] <=> $b['unique_id']));
Output:
array (
0 =>
array (
'id' => '434b5g6',
'unique_id' => 'banana',
'level' => 8,
),
)
array (
3 =>
array (
'id' => '07yburhg',
'unique_id' => 'pinapple',
'level' => 1,
),
)
Upvotes: 0
Reputation: 522382
Here a sample for PHP 5.3+:
$uniqueIds1 = array_map(function ($item) { return $item['unique_id']; }, $array1);
$uniqueIds2 = array_map(function ($item) { return $item['unique_id']; }, $array2);
$reallyUniqueIds = array_merge(array_diff($uniqueIds1, $uniqueIds2), array_diff($uniqueIds2, $uniqueIds1));
$filteredArray1 = array_filter($array1, function ($item) use ($reallyUniqueIds) {
return in_array($item['unique_id'], $reallyUniqueIds);
});
$filteredArray2 = array_filter($array2, function ($item) use ($reallyUniqueIds) {
return in_array($item['unique_id'], $reallyUniqueIds);
});
Explanation:
array_map(function ($item) { return $item['unique_id']; }, $array1)
This just extracts all unique_id
values into an array like array('banana', 'apple', ...)
.
array_merge(array_diff($uniqueIds1, $uniqueIds2), array_diff($uniqueIds2, $uniqueIds1));
This creates the diffs between the arrays both ways and merges them into one array, like:
array('banana', 'apple')
array('strawberry', 'apple')
-> array('banana', 'strawberry')
See array_diff
.
Then finally, this goes through the original arrays again to filter out all elements whose unique_key
is not in the array we created in the previous step:
array_filter($array1, function ($item) use ($reallyUniqueIds) {
return in_array($item['unique_id'], $reallyUniqueIds);
})
This just uses a custom callback function for array_filter
, which tells it to filter items where in_array($item['unique_id'], $reallyUniqueIds)
is false
.
Upvotes: 1
Reputation: 198116
The following is a function that operates on one, two or more arrays, first parameter is the key that is to be used for the unique id, any additional one is another array. Usage:
list($unique1, $unique2) = joined_uniquekey('unique_id', $array1, $array2);
Code:
function joined_uniquekey($key, $array1, $array2)
{
$arrays = func_get_args(); $key = array_shift($arrays);
$vkey = function($v) use ($key) {return $v[$key];};
$map = function($f) {return function(array $as) use ($f) {return array_map($f, $as);};};
$keys = array_count_values(call_user_func_array('array_merge', array_map($map($vkey), $arrays)));
foreach($keys as $k => $c) if ($c > 1) unset($keys[$k]);
$hkey = function($v) use ($key, $keys) {return isset($keys[$v[$key]]);};
$filter = function($f) {return function(array $a) use ($f) {return array_filter($a, $f);};};
return array_map($filter($hkey), $arrays);
}
Upvotes: 0
Reputation: 23312
foreach ( $array1 as $key1 => $innerarray1 ) {
foreach ( $array2 as $key2 => $innerarray2 ) {
if ($innerarray1['unique_id'] == $innerarray2['unique_id']) {
unset($array2[$key2]);
}
}
Now $array2 will have non common unique_id values in it
Upvotes: 0