Удалить дубликаты в массиве
Дубликаты в массиве удаляются через функцию array_unique() .
$array = array('PHP','MySQL','PHP','Zend'); $array = array_unique($array); /* Array([0] => PHP [1] => MySQL [3] => Zend) */
Стоит обратить внимание, что array_unique() удаляет только дубликаты в массиве, а индексы остаются прежними, как видно на примере выше. Сдвинуть индексы массива можно через функцию array_values() .
$array = array('PHP','MySQL','PHP','Zend'); $array = array_unique($array); // сдвинуть индексы $array = array_values($array); /* Array([0] => PHP [1] => MySQL [2] => Zend) */
Функция array_unique() регистрозависима. То есть для array_unique() элементы «php» и «PHP» это два разных элемента.
Авторизуйтесь, чтобы добавлять комментарии
array_unique
Принимает входной массив array и возвращает новый массив без повторяющихся значений.
Обратите внимание, что ключи сохранятся. Если в соответствии с заданными flags несколько элементов определяются как идентичные, то будут сохранены ключ и значение первого такого элемента.
Замечание: Два элемента считаются одинаковыми в том и только в том случае, если (string) $elem1 === (string) $elem2 . Другими словами: если у них одинаковое строковое представление, то будет использован первый элемент.
Список параметров
Можно использовать необязательный второй параметр flags для изменения поведения сравнения с помощью следующих значений:
- SORT_REGULAR — нормальное сравнение элементов (типы не меняются)
- SORT_NUMERIC — элементы сравниваются как числа
- SORT_STRING — элементы сравниваются как строки
- SORT_LOCALE_STRING — сравнивает элементы как строки, с учётом текущей локали.
Возвращаемые значения
Возвращает отфильтрованный массив.
Список изменений
Версия | Описание |
---|---|
7.2.0 | Если flags равен SORT_STRING , ранее массив array копировался, а не уникальные элементы удалялись (сохраняя значения цифровых индексов), но теперь создаётся новый массив путём добавления уникальных элементов. Это может привести к различным числовым индексам. |
Примеры
Пример #1 Пример использования array_unique()
$input = array( «a» => «green» , «red» , «b» => «green» , «blue» , «red» );
$result = array_unique ( $input );
print_r ( $result );
?>?php
Результат выполнения данного примера:
Array ( [a] => green [0] => red [1] => blue )
Пример #2 array_unique() и типы:
$input = array( 4 , «4» , «3» , 4 , 3 , «3» );
$result = array_unique ( $input );
var_dump ( $result );
?>?php
Результат выполнения данного примера:
Примечания
Замечание: Обратите внимание, что array_unique() не предназначена для работы с многомерными массивами.
Смотрите также
User Contributed Notes 32 notes
Create multidimensional array unique for any single key index.
e.g I want to create multi dimentional unique array for specific code
Code :
My array is like this,
$details = array(
0 => array( «id» => «1» , «name» => «Mike» , «num» => «9876543210» ),
1 => array( «id» => «2» , «name» => «Carissa» , «num» => «08548596258» ),
2 => array( «id» => «1» , «name» => «Mathew» , «num» => «784581254» ),
);
?>
You can make it unique for any field like id, name or num.
I have develop this function for same :
function unique_multidim_array ( $array , $key ) <
$temp_array = array();
$i = 0 ;
$key_array = array();
foreach( $array as $val ) <
if (! in_array ( $val [ $key ], $key_array )) <
$key_array [ $i ] = $val [ $key ];
$temp_array [ $i ] = $val ;
>
$i ++;
>
return $temp_array ;
>
?>
Now, call this function anywhere from your code,
something like this,
$details = unique_multidim_array ( $details , ‘id’ );
?>
Output will be like this :
$details = array(
0 => array( «id» => «1» , «name» => «Mike» , «num» => «9876543210» ),
1 => array( «id» => «2» , «name» => «Carissa» , «num» => «08548596258» ),
);
?>
modified code originally posted by Ghanshyam Katriya(anshkatriya at gmail) [highest voted comment here].
1. In php 7.4 counter $i breaks the function. Removed completely (imo was waste of keystrokes anyway).
2. I added second return value — array of duplicates. So you can take both and compare them (I had to).
Example array (copy-paste from original post):
$details = array(
0 => array( «id» => «1» , «name» => «Mike» , «num» => «9876543210» ),
1 => array( «id» => «2» , «name» => «Carissa» , «num» => «08548596258» ),
2 => array( «id» => «1» , «name» => «Mathew» , «num» => «784581254» ),
);
?>
Function:
function unique_multidim_array ( $array , $key ) : array $uniq_array = array();
$dup_array = array();
$key_array = array();
foreach( $array as $val ) if (! in_array ( $val [ $key ], $key_array )) $key_array [] = $val [ $key ];
$uniq_array [] = $val ;
/*
# 1st list to check:
# echo «ID or sth: » . $val[‘building_id’] . «; Something else: » . $val[‘nodes_name’] . (. ) «\n»;
*/
> else $dup_array [] = $val ;
/*
# 2nd list to check:
# echo «ID or sth: » . $val[‘building_id’] . «; Something else: » . $val[‘nodes_name’] . (. ) «\n»;
*/
>
>
return array( $uniq_array , $dup_array , /* $key_array */ );
>
?>
Usage:
list( $unique_addresses , $duplicates , /* $unique_keys */ ) = unique_multidim_array ( $details , ‘id’ );
?>
Then:
var_dump($unique_addresses);
or
var_dump($duplicates);
or foreach or whatever. Personally I just echo-ed 1st and then 2nd (both DOUBLE COMMENTED) list in function itself (then copied both to notepad++ and compared them — just to be 100% sure), but in case you want to do something else with it — enjoy 🙂
Plus — as a bonus — you also get an array of UNIQUE keys you searched for (just uncomment >$key_array< in both: function return and function call code).
From example array code returns:
var_dump($unique_addresses);
array(2) [0]=>
array(3) [«id»]=>
string(1) «1»
[«name»]=>
string(4) «Mike»
[«num»]=>
string(10) «9876543210»
>
[1]=>
array(3) [«id»]=>
string(1) «2»
[«name»]=>
string(7) «Carissa»
[«num»]=>
string(11) «08548596258»
>
>
P.S.: in my — practical — case of DB querying I got around 4k uniques and 15k dupes 🙂
I find it odd that there is no version of this function which allows you to use a comparator callable in order to determine items equality (like array_udiff and array_uintersect). So, here’s my version for you:
function array_uunique (array $array , callable $comparator ): array $unique_array = [];
do $element = array_shift ( $array );
$unique_array [] = $element ;
$array = array_udiff (
$array ,
[ $element ],
$comparator
);
> while ( count ( $array ) > 0 );
return $unique_array ;
>
?>
And here is a test code:
public function __construct ( int $a ) $this -> a = $a ;
>
>
$array_of_objects = [new Foo ( 2 ), new Foo ( 1 ), new Foo ( 3 ), new Foo ( 2 ), new Foo ( 2 ), new Foo ( 1 )];
$comparator = function ( Foo $foo1 , Foo $foo2 ): int return $foo1 -> a $foo2 -> a ;
>;
var_dump ( array_uunique ( $array_of_objects , $comparator )); // should output [Foo(2), Foo(1), Foo(3)]
?>
In reply to performance tests array_unique vs foreach.
In PHP7 there were significant changes to Packed and Immutable arrays resulting in the performance difference to drop considerably. Here is the same test on php7.1 here;
http://sandbox.onlinephpfunctions.com/code/2a9e986690ef8505490489581c1c0e70f20d26d1
$max = 770000; //large enough number within memory allocation
$arr = range(1,$max,3);
$arr2 = range(1,$max,2);
$arr = array_merge($arr,$arr2);
$time = -microtime(true);
$res1 = array_unique($arr);
$time += microtime(true);
echo «deduped to «.count($res1).» in «.$time;
// deduped to 513333 in 1.0876770019531
$time = -microtime(true);
$res2 = array();
foreach($arr as $key=>$val) <
$res2[$val] = true;
>
$res2 = array_keys($res2);
$time += microtime(true);
echo «
deduped to «.count($res2).» in «.$time;
// deduped to 513333 in 0.054931879043579
It’s often faster to use a foreache and array_keys than array_unique:
$max = 1000000 ;
$arr = range ( 1 , $max , 3 );
$arr2 = range ( 1 , $max , 2 );
$arr = array_merge ( $arr , $arr2 );
$time = — microtime ( true );
$res1 = array_unique ( $arr );
$time += microtime ( true );
echo «deduped to » . count ( $res1 ). » in » . $time ;
// deduped to 666667 in 32.300781965256
$time = — microtime ( true );
$res2 = array();
foreach( $arr as $key => $val ) <
$res2 [ $val ] = true ;
>
$res2 = array_keys ( $res2 );
$time += microtime ( true );
echo «
deduped to » . count ( $res2 ). » in » . $time ;
// deduped to 666667 in 0.84372591972351
I needed to identify email addresses in a data table that were replicated, so I wrote the array_not_unique() function:
function array_not_unique ( $raw_array ) $dupes = array();
natcasesort ( $raw_array );
reset ( $raw_array );
$old_key = NULL ;
$old_value = NULL ;
foreach ( $raw_array as $key => $value ) if ( $value === NULL ) < continue; >
if ( $old_value == $value ) $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 );
?>
Taking the advantage of array_unique, here is a simple function to check if an array has duplicate values.
It simply compares the number of elements between the original array and the array_uniqued array.
function array_has_duplicates (array $array )
<
$uniq = array_unique ( $array );
return count ( $uniq ) != count ( $array );
>
Case insensitive; will keep first encountered value.
function array_iunique ( $array ) <
$lowered = array_map ( ‘strtolower’ , $array );
return array_intersect_key ( $array , array_unique ( $lowered ));
>
As for PHP 7.1.12, this is the comparison between array_keys(array_flip()), array_flip(array_flip()), for each elimination and array_unique. The array_keys(array_flip()) is the fastest method to remove duplication values from a single dimension array:
$max = 1000000 ;
$arr = range ( 1 , $max , 3 );
$arr2 = range ( 1 , $max , 2 );
$arr = array_merge ( $arr , $arr2 );
$time = — microtime ( true );
$res1 = array_unique ( $arr );
$time += microtime ( true );
echo «
deduped to » . count ( $res1 ). » in » . $time ;
// deduped to 666667 in 0.78185796737671
// memory used: 33558528
$time = — microtime ( true );
$res2 = array_flip ( array_flip ( $arr ));
$time += microtime ( true );
echo «
deduped to » . count ( $res2 ). » in » . $time ;
// deduped to 666667 in 0.072191953659058
// memory used: 3774873
$time = — microtime ( true );
$res3 = array();
foreach( $arr as $key => $val ) $res3 [ $val ] = true ;
>
$res3 = array_keys ( $res3 );
$time += microtime ( true );
echo «
deduped to » . count ( $res3 ). » in » . $time ;
// deduped to 666667 in 0.095494985580444
// memory used: 33558528
$time = — microtime ( true );
$res4 = array_keys ( array_flip ( $arr ));
$time += microtime ( true );
echo «
deduped to » . count ( $res4 ). » in » . $time ;
// deduped to 666667 in 0.05807900428772
// memory used: 33558528
Here is a solution to make unique values keeping empty values for an array with keys :
function array_unique_kempty ( $array ) $values = array_unique ( $array );
$return = array_combine ( array_keys ( $array ), array_fill ( 0 , count ( $array ), null ));
return array_merge ( $return , $values );
>
$myArray = [
«test1» => «aaa» ,
«test2» => null ,
«test3» => «aaa» ,
«test4» => «bbb» ,
«test5» => null ,
«test6» => «ccc» ,
«test7» => «ddd» ,
«test8» => «ccc»
];
echo «
" . print_r ( array_unique_kempty ( $myArray ), true ). "
» ;
Following the Ghanshyam Katriya idea, but with an array of objects, where the $key is related to object propriety that you want to filter the uniqueness of array:
recursive array unique for multiarrays
function super_unique ( $array )
$result = array_map ( «unserialize» , array_unique ( array_map ( «serialize» , $array )));
foreach ( $result as $key => $value )
if ( is_array ( $value ) )
$result [ $key ] = super_unique ( $value );
>
>
If you find the need to get a sorted array without it preserving the keys, use this code which has worked for me:
$array = array( «hello» , «fine» , «good» , «fine» , «hello» , «bye» );
$get_sorted_unique_array = array_values ( array_unique ( $array ));
?>
The above code returns an array which is both unique and sorted from zero.
My object unique function:
function object_unique ( $obj ) $objArray = (array) $obj ;
$objArray = array_intersect_assoc ( array_unique ( $objArray ), $objArray );
foreach( $obj as $n => $f ) if( ! array_key_exists ( $n , $objArray ) ) unset( $obj -> $n );
>
return $obj ;
>
?>
And these code:
class Test public $pr0 = ‘string’ ;
public $pr1 = ‘string1’ ;
public $pr2 = ‘string’ ;
public $pr3 = ‘string2’ ;
>
var_dump ( object_unique ( $obj ) );
?>
returns:
object(Test)[1]
public ‘pr0’ => string ‘string’ (length=6)
public ‘pr1’ => string ‘string1’ (length=7)
public ‘pr3’ => string ‘string2’ (length=7)
This is a script for multi_dimensional arrays
function remove_dup ( $matriz ) <
$aux_ini =array();
$entrega =array();
for( $n = 0 ; $n < count ( $matriz ); $n ++)
<
$aux_ini []= serialize ( $matriz [ $n ]);
>
$mat = array_unique ( $aux_ini );
for( $n = 0 ; $n < count ( $matriz ); $n ++)
$entrega []= unserialize ( $mat [ $n ]);