使用php在数组中查找唯一数据

I have 2 arrays that look sort of like this:

Array =>

[0] Array( [id]=434b5g6 [unique_id]=banana [level]=8)

[1] Array( [id]=bfrfnr [unique_id]=apple [level]=4)

[2] Array( [id]=yt347509 [unique_id]=grapefruit [level]=9 )

[3] Array( [id]=456645 [unique_id]=strawberry [level]=1)


Array =>

[0] Array( [id]=gon235g6 [unique_id]=strawberry [level]=8 )

[1] Array( [id]=bfrfnr [unique_id]=apple [level]=4 )

[2] Array( [id]=logujtng9 [unique_id]=grapefruit [level]=6 )

[3] Array( [id]=07yburhg [unique_id]=pinapple [level]=1)

I need a way to remove the elements in which the [unique_id] exists in both arrays so that im left with 2 arrays which only contain elements that do not exist in the other. Eg if we were to run the script on these 2 arrays i should be left with:

Array =>
[0] Array( [id]=434b5g6 [unique_id]=banana [level]=8)

Array =>
[0] Array( [id]=07yburhg [unique_id]=pinapple [level]=1)

Im really not sure how to do this though. I know there is array_diff but this only works for single level arrays. Im using a multi level one and only trageting the [unique_id] part of it. Any help would be really appreciated.

  1. Get the unique ids out of both arrays.
  2. Calculate their difference (items that are not in both).
  3. Filter the original arrays to items that are in the diff.

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.

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

Try:


print_r(array_unique($arr1 + $arr2));

  1. join all "unique_id" across all arrays.
  2. filter out duplicates to get uniques.
  3. filter all arrays based on the uniques.

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);
}