Reputation: 4252
There are many solutions to removing duplicates from multidimensional arrays in PHP but I haven't found one which detects duplicates no matter of case, but preserves them in the output:
// Sample data
$arr = [
['id' => 1, 'term' => 'Hello'],
['id' => 1, 'term' => 'hello'],
['id' => 2, 'term' => 'Hello'],
['id' => 2, 'term' => 'hello']
];
// Desired output
$arr = [
['id' => 1, 'term' => 'Hello'],
['id' => 2, 'term' => 'Hello']
];
// Ex 1. case sensitive, preserves case
$serialized = array_map('serialize', $arr);
$unique = array_unique($serialized);
$unique = array_intersect_key($arr, $unique);
// Ex 2. case insensitive, doesn't preserve case
$unique = array_map('unserialize',
array_unique(
array_map('strtolower',
array_map('serialize',$arr)
)
)
);
Upvotes: 4
Views: 256
Reputation: 40653
There's no built-in way. You can however define a custom comparator and a sort:
function compare($a, $b) {
ksort($a);
ksort($b); //To ignore keys not in the same order
return strtolower(serialize($a)) <=> strtolower(serialize($b));
}
function array_unique_callback($arr, $callback) {
$copy = $arr;
usort($copy, $callback);
$previous = null;
$arr = [];
foreach ($copy as $key => $value) {
if ($previous === null || $callback($previous,$value) !== 0) {
$previous = $value;
$arr[$key] = $value;
}
}
return $arr;
}
// Sample data
$arr = [
['id' => 1, 'term' => 'Hello'],
['id' => 2, 'term' => 'hello'],
['id' => 1, 'term' => 'hello'],
['id' => 2, 'term' => 'Hello']
];
print_r(array_unique_callback($arr, 'compare'));
Note this will not work for multi-dimensional sub-arrays unless their keys are in the same order. You might need to do a recursive ksort to get that to work.
Upvotes: 0
Reputation: 57121
Rather than manipulating the content of the array, this creates a key to the array (in a similar manner to how you manipulate the main array) and then when you combine the key with the data (using array_combine()
) the duplicates are removed (as only 1 key can exist in the result)...
$arr = [
['id' => 1, 'term' => 'Hello'],
['id' => 1, 'term' => 'hello'],
['id' => 1, 'term' => 'Hello'],
['id' => 2, 'term' => 'Hello']
];
$key = array_map("serialize", $arr);
$key = array_map("strtolower", $key);
$new = array_combine($key, $arr);
print_r(array_values($new));
gives...
Array
(
[0] => Array
(
[id] => 1
[term] => Hello
)
[1] => Array
(
[id] => 2
[term] => Hello
)
)
For the vertically challenged, it can be wrapped into 1 (although less readable) line ...
$new = array_values(array_combine(array_map("strtolower", array_map("serialize", $arr)), $arr));
Upvotes: 3