PHP: Check for duplicate values in a multidimensional array
I want to check its values and find duplicates (i.e. keys 0, 2 and 3) leaving just one key — value pair deleting the others, resulting in somthing like this:
Array( [0] => Array("a", "b", "c") [1] => Array("x", "y", "z") [2] => Array("a", "x", "z") )
6 Answers 6
This will remove duplicate items from your array using array_unique() :
$new_arr = array_unique($arr, SORT_REGULAR);
as per php document «Note that array_unique() is not intended to work on multi dimensional arrays.». It can be seen from the given link.
@enam I think it just means that array_unique doesn’t flatten the array to find the uniques. (btw, +1)
You can simply do it using in_array()
$data = Array( 0 => Array("a", "b", "c"), 1 => Array("x", "y", "z"), 2 => Array("a", "b", "c"), 3 => Array("a", "b", "c"), 4 => Array("a", "x", "z"), ); $final = array(); foreach ($data as $array) < if(!in_array($array, $final))< $final[] = $array; >>
which will get you something like
array(3) < [0] =>array(3) < [0] =>string(1) "a" [1] => string(1) "b" [2] => string(1) "c" > [1] => array(3) < [0] =>string(1) "x" [1] => string(1) "y" [2] => string(1) "z" > [2] => array(3) < [0] =>string(1) "a" [1] => string(1) "x" [2] => string(1) "z" > >
You can go smart with serialization for comparison of arrays.
var_dump(makeUnique($data)); function makeUnique(array $data)
$arr = . ; $final = array(); sort($arr); foreach ($arr as $el)
This is a more efficient 1 solution (log n + n instead of quadratic) but it relies on a total order between all the elements of the array, which you may not have (e.g. if the inner arrays have objects).
1 More efficient than using in_array . Turns out array_unique actually uses this algorithm, so it has the same shortcomings.
Check and return duplicates array php
I would like to check if my array has any duplicates and return the duplicated values in an array. I want this to be as efficient as possible. Example:
$array = array( 1, 2, 2, 4, 5 ); function return_dup($array); // should return 2 $array2 = array( 1, 2, 1, 2, 5 ); function return_dup($array2); // should return an array with 1,2
11 Answers 11
this will be ~100 times faster than array_diff
$dups = array(); foreach(array_count_values($arr) as $val => $c) if($c > 1) $dups[] = $val;
Did a very quick benckmark and for me your method is only only coming out twice as fast as JAL’s array_diff method, not 100 times faster.
Note that array_count_values only accepts string and integer values, so if your input array might include other types of values, this is not a good option. But it does work for the example in the question where it looks like the situation is dependably just an array of integers.
You can get the difference of the original array and a copy without duplicates using array_unique and array_diff_assoc :
array_diff_assoc($arr, array_unique($arr))
function showDups($array) < $array_temp = array(); foreach($array as $val) < if (!in_array($val, $array_temp)) < $array_temp[] = $val; >else < echo 'duplicate = ' . $val . '
'; > > > $array = array(1,2,2,4,5); showDups($array);
function returndup($array) < $results = array(); $duplicates = array(); foreach ($array as $item) < if (in_array($item, $results)) < $duplicates[] = $item; >$results[] = $item; > return $duplicates; >
Now it returns an array of duplicates. In the first post there was no notice that is needs to return multiple duplicates, so don’t blame me!
in addition to gumbo’s answer:
I did some tests and indeed @user187291’s variant is the fastest. But, it turns out that @Gumbo’s and @faebser’s alternative are almost as fast, @faebser’s being just slightly faster than @Gumbo’s and sometimes even fastest of all.
$array = array(1, "hello", 1, "world", "hello"); $times = 1000000; $start = microtime(true); for ($i = 0; $i < $times; $i++) < $dups = array(); foreach(array_count_values($array) as $val =>$c) if( $c > 1) $dups[] = $val; > $end = microtime(true); echo 'variant 1 (user187291): ' . ($end - $start); echo '
'; $start = microtime(true); for ($i = 0; $i < $times; $i++) $dups = array_unique(array_diff_assoc($array, array_unique($array))); $end = microtime(true); echo 'variant 2 (JAL): ' . ($end - $start); echo '
'; $start = microtime(true); for ($i = 0; $i < $times; $i++) $dups = array_diff_assoc($array, array_unique($array)); $end = microtime(true); echo 'variant 3 (Gumbo): ' . ($end - $start); echo '
'; $start = microtime(true); for ($i = 0; $i < $times; $i++) $dups = array_diff_key($array, array_unique($array)); $end = microtime(true); echo 'variant 4 (faebser): ' . ($end - $start); echo '
';
php: check if an array has duplicates
I’m sure this is an extremely obvious question, and that there’s a function that does exactly this, but I can’t seem to find it. In PHP, I’d like to know if my array has duplicates in it, as efficiently as possible. I don’t want to remove them like array_unique does, and I don’t particularly want to run array_unique and compare it to the original array to see if they’re the same, as this seems very inefficient. As far as performance is concerned, the «expected condition» is that the array has no duplicates. I’d just like to be able to do something like
if (no_dupes($array)) // this deals with arrays without duplicates else // this deals with arrays with duplicates
Is there any obvious function I’m not thinking of?
How to detect duplicate values in PHP array?
has the right title, and is a very similar question, however if you actually read the question, he’s looking for array_count_values.
Do you just want to know if there are any duplicates or the quantity and value of said duplicates etc?
Honestly I think if(count($array) == count(array_unique($array))) is the best you can get. You have to traverse the array this way or another and I think the built-in are optimized for that. array_flip could be considered too.
@Felix, you can do better than that. That does three loops, one to create the unique array, one to count it, and one to count the original.
@Mike Sherov: Are you sure? I couldn’t find anything about it, but I had hoped that PHP arrays have some internal property that keeps track of the length. Do you have an information about this? I would be very interested.
Return only duplicated entries from an array (case-insensitive)
I believe without the first array_unique , if the original array had a value three times, this would return an array that had it twice; or if the original had it four times, the return would have it three times, etc.
$value) < if ($value === NULL) < continue; >if (strcasecmp($old_value, $value) === 0) < $dupes[$old_key] = $old_value; $dupes[$key] = $value; >$old_value = $value; $old_key = $key; > return $dupes; > $raw_array = array(); $raw_array[1] = 'abc@xyz.com'; $raw_array[2] = 'def@xyz.com'; $raw_array[3] = 'ghi@xyz.com'; $raw_array[4] = 'abc@xyz.com'; // Duplicate $common_stuff = array_not_unique($raw_array); var_dump($common_stuff);
You will need to make your function case insensitive to get the «Hello» => «hello» result you are looking for, try this method:
$arr = array(1=>'1233',2=>'12334',3 =>'Hello' ,4=>'hello', 5=>'U'); // Convert every value to uppercase, and remove duplicate values $withoutDuplicates = array_unique(array_map("strtoupper", $arr)); // The difference in the original array, and the $withoutDuplicates array // will be the duplicate values $duplicates = array_diff($arr, $withoutDuplicates); print_r($duplicates);
Edit by @AlixAxel:
This answer is very misleading. It only works in this specific condition. This counter-example:
$arr = array(1=>'1233',2=>'12334',3 =>'Hello' ,4=>'HELLO', 5=>'U');
Fails miserably. Also, this is not the way to keep duplicates:
array_diff($arr, array_unique($arr));
Since one of the duplicated values will be in array_unique , and then chopped off by array_diff .
Edit by @RyanDay:
So look at @Srikanth’s or @Bucabay’s answer, which work for all cases (look for case insensitive in Bucabay’s), not just the test data specified in the question.
Count and display occurrences of unique values in an array
I am working with a one dimensional array in PHP. I would like to detect the presence of duplicate values, then count the number of duplicate values and output the results. For example, given the following array:
$array = [ 'apple', 'orange', 'pear', 'banana', 'apple', 'pear', 'kiwi', 'kiwi', 'kiwi' ];
apple (2) orange pear (2) banana kiwi (3)
15 Answers 15
$array = array('apple', 'orange', 'pear', 'banana', 'apple', 'pear', 'kiwi', 'kiwi', 'kiwi'); print_r(array_count_values($array));
Array ( [apple] => 2 [orange] => 1 [pear] => 2 etc. )
This solution does not cover any non-integer and non-string values and in conclusion it produces sideffects.
if(count(array_unique($array)) else < // Array does not have duplicates >
This solution does not cover any non-integer and non-string values and in conclusion it produces sideffects. Using array_unique($array, SORT_REGULAR) forces PHP to check elements normally without changing the type, but it’s a loose comparison. So different instances of one class with same content will be uniquified.
function array_not_unique( $a = array() )
array ( 4 => 'apple', 5 => 'pear', 7 => 'kiwi', 8 => 'kiwi', )
Extended to only give list of duplicate values (what I needed): return array_values(array_unique(array_diff_key($a, array_unique($a))));
You could try turning that array into a associative array with the fruits as keys and the number of occurrences as values. Bit long-winded, but it looks like:
$array = array('apple', 'orange', 'pear', 'banana', 'apple', 'pear', 'kiwi', 'kiwi', 'kiwi'); $new_array = array(); foreach ($array as $key => $value) < if(isset($new_array[$value])) $new_array[$value] += 1; else $new_array[$value] = 1; >foreach ($new_array as $fruit => $n) < echo $fruit; if($n >1) echo "($n)"; echo "
"; >
To get rid use array_unique() . To detect if have any use count(array_unique()) and compare to count($array) .
Perhaps something like this (untested code but should give you an idea)?
$new = array(); foreach ($array as $value)
Then you’ll get a new array with the values as keys and their value is the number of times they existed in the original array.
Stuff them into a map (pseudocode)
map[string -> int] $m foreach($word in $array)
I didn’t find the answer I was looking for, so I wrote this function. This will make an array that contains only the duplicates between the two arrays, but not print the number of times an element is duplicated, so it’s not directly answering the question, but I’m hoping it’ll help someone in my situation.
function findDuplicates($array1,$array2) < $combined = array_merge($array1,$array2); $counted = array_count_values($combined); $dupes = []; $keys = array_keys($counted); foreach ($keys as $key) < if ($counted[$key] >1) <$dupes[] = $key;>> sort($dupes); return $dupes; > $array1 = [1,2,3,4,5]; $array2 = [4,5,6,7,8]; $dupes = findDuplicates($array1,$array2); print_r($dupes);
$data = ['outer', 'inner', 'sole', 'sole', 'outer', 'outer']; $result = max(array_count_values($data)); if($result > 1)
I think this way is shorter and cleaner.