How can I remove duplicate values from a multi-dimensional array in PHP?
Example array:
Array
[
[0] => Array
[
[0] => abc
[1] => def
]
[1] => Array
[
[0] => ghi
[1] => jkl
]
[2] => Array
[
[0] => mno
[1] => pql
]
[3] => Array
[
[0] => abc
[1] => def
]
[4] => Array
[
[0] => ghi
[1] => jkl
]
[5] => Array
[
[0] => mno
[1] => pql
]
]
asked Nov 21, 2008 at 2:50
1
Here is another way. No intermediate variables are saved.
We used this to de-duplicate results from a variety of overlapping queries.
$input = array_map["unserialize", array_unique[array_map["serialize", $input]]];
jeromegamez
3,1521 gold badge22 silver badges36 bronze badges
answered Jun 3, 2009 at 18:12
daveilersdaveilers
7,4261 gold badge16 silver badges4 bronze badges
13
Since 5.2.9 you can use array_unique[]
if you use the SORT_REGULAR
flag like so:
array_unique[$array, SORT_REGULAR];
This makes the function compare elements for equality as if $a == $b
were being used, which is
perfect for your case.
Output
Array
[
[0] => Array
[
[0] => abc
[1] => def
]
[1] => Array
[
[0] => ghi
[1] => jkl
]
[2] => Array
[
[0] => mno
[1] => pql
]
]
Keep in mind, though, that the documentation states:
array_unique[]
is not intended to work on multi dimensional arrays.
answered Aug 22, 2013 at 7:01
Ja͢ckJa͢ck
168k36 gold badges255 silver badges305 bronze badges
14
I had a similar problem but I found a 100% working solution for it.
Martin
21.2k8 gold badges62 silver badges117 bronze badges
answered May 9, 2012 at 10:48
3
Another way. Will preserve keys as well.
function array_unique_multidimensional[$input]
{
$serialized = array_map['serialize', $input];
$unique = array_unique[$serialized];
return array_intersect_key[$input, $unique];
}
answered Nov 21, 2008 at 14:36
OISOIS
9,5921 gold badge31 silver badges41 bronze badges
1
Array
[
[0] => Array
[
[id] => 1
[name] => john
]
[1] => Array
[
[id] => 2
[name] => smith
]
[2] => Array
[
[id] => 3
[name] => john
]
[3] => Array
[
[id] => 4
[name] => robert
]
]
$temp = array_unique[array_column[$array, 'name']];
$unique_arr = array_intersect_key[$array, $temp];
This will remove the duplicate names from array. unique by key
answered Feb 23, 2018 at 6:34
Mahak ChoudharyMahak Choudhary
1,0661 gold badge15 silver badges13 bronze badges
2
If "remove duplicates" means "remove duplicates, but let one there", a solution might be to
apply the array_unique[...]
on the "identifier column" first and then to remove in the original array all the keys, that have been removed from the column array:
$array = [
[
'id' => '123',
'foo' => 'aaa',
'bar' => 'bbb'
],
[
'id' => '123',
'foo' => 'ccc',
'bar' => 'ddd'
],
[
'id' => '567',
'foo' => 'eee',
'bar' => 'fff'
]
];
$ids = array_column[$array, 'id'];
$ids = array_unique[$ids];
$array = array_filter[$array, function [$key, $value] use [$ids] {
return in_array[$value, array_keys[$ids]];
}, ARRAY_FILTER_USE_BOTH];
The result is:
Array
[
[0] => Array
[
[id] => 123
[foo] => aaa
[bar] => bbb
]
[2] => Array
[
[id] => 567
[foo] => eee
[bar] => fff
]
]
answered May 20, 2016 at 22:14
automatixautomatix
13k24 gold badges97 silver badges218 bronze badges
1
The user comments on the array_unique[] documentation have many solutions to this. Here is one of them:
kenrbnsn at rbnsn dot com
27-Sep-2005 12:09Yet another Array_Unique for multi-demensioned arrays. I've only tested this on two-demensioned arrays, but it could probably be generalized for more, or made to use recursion.
This function uses the serialize, array_unique, and unserialize functions to do the work.
function multi_unique[$array] { foreach [$array as $k=>$na] $new[$k] = serialize[$na]; $uniq = array_unique[$new]; foreach[$uniq as $k=>$ser] $new1[$k] = unserialize[$ser]; return [$new1]; }
This is from //ca3.php.net/manual/en/function.array-unique.php#57202.
Manoj Sharma
1,4672 gold badges13 silver badges20 bronze badges
answered Nov 21, 2008 at 3:07
Paige RutenPaige Ruten
167k36 gold badges175 silver badges195 bronze badges
0
if you need to eliminate duplicates on specific keys, such as a mysqli id, here's a simple funciton
function search_array_compact[$data,$key]{
$compact = [];
foreach[$data as $row]{
if[!in_array[$row[$key],$compact]]{
$compact[] = $row;
}
}
return $compact;
}
Bonus Points You can pass an array of keys and add an outer foreach, but it will be 2x slower per additional key.
answered Nov 8, 2014 at 7:17
r3wtr3wt
4,5722 gold badges31 silver badges55 bronze badges
2
if you have an array like this:
[users is the name of the array]
Array=>
[0] => [array]
'user' => 'john'
'age' => '23'
[1] => [array]
'user' => 'jane'
'age' => '20'
[2]=> [array]
'user' => 'john'
'age' => '23'
and you want to delete duplicates...then:
$serialized = array[];
for [$i=0; $i < sizeof[$users]; $i++] {
$test = in_array[$users['user'], $serialized];
if [$test == false] {
$serialized[] = $users['user'];
}
}
can be a solution :P
answered Aug 7, 2015 at 18:45
LimonLimon
1,7226 gold badges31 silver badges58 bronze badges
1
Lots of person asked me how to make Unique multidimensional array. I have taken reference from your comment and it helps me.
First of All, Thanks to @jeromegamez @daveilers for your solution. But every time i gave the answer, they asked me how this 'serialize' and 'unserialize' works. That's why i want to share the reason of this with you so that it will help more people to understand the concept behind this.
I am explaining why we use 'serialize' and 'unserialize' in steps :
Step 1: Convert the multidimensional array to one-dimensional array
To convert the multidimensional array to a one-dimensional array, first generate byte stream representation of all the elements [including nested arrays] inside the array. serialize[] function can generate byte stream representation of a value. To generate byte stream representation of all the elements, call serialize[] function inside array_map[] function as a callback function. The result will be a one dimensional array no matter how many levels the multidimensional array has.
Step 2: Make the values unique
To make this one dimensional array unique, use array_unique[] function.
Step 3: Revert it to the multidimensional array
Though the array is now unique, the values looks like byte stream representation. To revert it back to the multidimensional array, use unserialize[] function.
$input = array_map["unserialize", array_unique[array_map["serialize", $input]]];
Thanks again for all this.
answered Sep 1, 2016 at 11:29
ManishManish
3,2131 gold badge20 silver badges24 bronze badges
A very easy and logical way to Unique a multi dimension array is as follows,
If you have array like this:
Array
[
[Key1] => Array
[
[0] => Value1
[1] => Value2
[2] => Value1
[3] => Value3
[4] => Value1
]
[Key2] => Array
[
[0] => Value1
[1] => Value2
[2] => Value1
[3] => Value3
[4] => Value4
]
]
use foreach
to solve this:
foreach[$array as $k=>$v]{
$unique=array_unique[$v];
$array[$k]=$unique;
}
it will give you following result:
Array
[
[Key1] => Array
[
[0] => Value1
[1] => Value2
[3] => Value3
]
[Key2] => Array
[
[0] => Value1
[1] => Value2
[3] => Value3
[4] => Value4
]
]
and if you want to rearrange the order of the keys,
foreach[$array as $k=>$v]{
$unique= array_values[array_unique[$v]];
$array[$k]=$unique;
}
This operation will give you arranged key values like this:
Array
[
[Key1] => Array
[
[0] => Value1
[1] => Value2
[2] => Value3
]
[Key2] => Array
[
[0] => Value1
[1] => Value2
[2] => Value3
[3] => Value4
]
]
I hope this will clear everything.
answered Jan 19, 2018 at 13:22
1
An easy to read solution, probably not the most efficient:
function arrayUnique[$myArray]{
if[!is_array[$myArray]]
return $myArray;
foreach [$myArray as &$myvalue]{
$myvalue=serialize[$myvalue];
}
$myArray=array_unique[$myArray];
foreach [$myArray as &$myvalue]{
$myvalue=unserialize[$myvalue];
}
return $myArray;
}
graham.reeds
15.9k17 gold badges70 silver badges133 bronze badges
answered Jun 19, 2009 at 19:44
pixelinepixeline
17.5k11 gold badges80 silver badges109 bronze badges
As people are saying array_unique[]
is very slow, here is a snippet I use for one level multidimensional array.
$serialized_array = array_map["serialize", $input];
foreach [$serialized_array as $key => $val] {
$result[$val] = true;
}
$output = array_map["unserialize", [array_keys[$result]]];
Reference first user contributed note of array_unique[]
function page in php.net
answered Apr 18, 2015 at 19:01
AnujAnuj
3234 silver badges13 bronze badges
0
An alternative to serialize and unique
$test = [
['abc','def'],
['ghi','jkl'],
['mno','pql'],
['abc','def'],
['ghi','jkl'],
['mno','pql'],
];
$result = array_reduce[
$test,
function[$carry,$item]{
if[!in_array[$item,$carry]] {
array_push[$carry,$item];
}
return $carry;
},
[]
];
var_dump[$result];
/*
php unique.php
array[3] {
[0] =>
array[2] {
[0] =>
string[3] "abc"
[1] =>
string[3] "def"
}
[1] =>
array[2] {
[0] =>
string[3] "ghi"
[1] =>
string[3] "jkl"
}
[2] =>
array[2] {
[0] =>
string[3] "mno"
[1] =>
string[3] "pql"
}
}
*/
answered Nov 6, 2014 at 23:04
1
I've given this problem a lot of thought and have determined that the optimal solution should follow two rules.
- For scalability, modify the array in place; no copying to a new array
- For performance, each comparison should be made only once
With that in mind and given all of PHP's quirks, below is the solution I came up with. Unlike some of the other answers, it has the ability to remove elements based on whatever key[s] you want. The input array is expected to be numeric keys.
$count_array = count[$input];
for [$i = 0; $i < $count_array; $i++] {
if [isset[$input[$i]]] {
for [$j = $i+1; $j < $count_array; $j++] {
if [isset[$input[$j]]] {
//this is where you do your comparison for dupes
if [$input[$i]['checksum'] == $input[$j]['checksum']] {
unset[$input[$j]];
}
}
}
}
}
The only drawback is that the keys are not in order when the iteration completes. This
isn't a problem if you're subsequently using only foreach loops, but if you need to use a for loop, you can put $input = array_values[$input];
after the above to renumber the keys.
answered Mar 5, 2015 at 14:04
SnakeSnake
811 silver badge4 bronze badges
1
try this solution for [n] Dimensional array with non-restricted length
for example this array
$arr= [
0 => [0=>"a" , 1=>"b" , 2=>"c" ] ,
1 => [0=>"x" , 1=>"b" , 2=>"a", 3=>"p"],
2=> [
[
0=>"y" ,
1=>"b" ,
2=> [0=>"x" , 1=>"m" , 2=>"a"]
],
1=>"z" ,
2=>"v"
]
];
This would be the solution
$ar2=[];
$ar3=[];
function test[$arr]{
global $ar2,$ar3;
if[is_array[$arr]]{
return array_map["test",$arr];
}
if[!isset[$ar2[$arr]]]{
$ar2[$arr]=1;
$ar3[]=$arr;
}
}
array_map["test",$arr];
print_r[$ar3];
answered May 26 at 13:44
Based on the Answer marked as correct, adding my answer. Small code added just to reset the indices-
$input = array_values[array_map["unserialize", array_unique[array_map["serialize", $inputArray]]]];
answered Feb 14, 2020 at 11:01
GaganGagan
2942 silver badges15 bronze badges
1