php: проверить, есть ли в массиве дубликаты - PullRequest
54 голосов
/ 30 июня 2010

Я уверен, что это чрезвычайно очевидный вопрос, и что есть функция, которая делает именно это, но я не могу найти ее. В PHP я хотел бы знать, насколько эффективно в моем массиве есть дубликаты. Я не хочу удалять их, как array_unique, и я не хочу запускать array_unique и сравнивать его с исходным массивом, чтобы увидеть, совпадают ли они, поскольку это кажется очень неэффективным. Что касается производительности, то «ожидаемым условием» является отсутствие в массиве дубликатов.

Я просто хотел бы иметь возможность сделать что-то вроде

if (no_dupes($array))
    // this deals with arrays without duplicates
else
    // this deals with arrays with duplicates

Есть ли какая-то очевидная функция, о которой я не думаю?
Как обнаружить повторяющиеся значения в массиве PHP?
имеет правильный заголовок, и это очень похожий вопрос, однако, если вы действительно прочитаете вопрос, он ищет array_count_values.

Ответы [ 13 ]

182 голосов
/ 30 июня 2010

Я знаю, что вы не после array_unique().Однако вы не найдете магическую очевидную функцию и не будете писать ее быстрее, чем использование собственных функций.

Я предлагаю:

function array_has_dupes($array) {
   // streamline per @Felix
   return count($array) !== count(array_unique($array));
}

Настройте второй параметр array_unique() для удовлетворения ваших потребностей сравнения.

48 голосов
/ 26 апреля 2017

⚡ РАБОЧЕЕ РЕШЕНИЕ ⚡

Если вы заботитесь о производительности и микрооптимизации, проверьте эту строку:

function no_dupes(array $input_array) {
    return count($input_array) === count(array_flip($input_array));
}

Описание:

Функция сравнивает количество элементов массива в $input_array с array_flip 'ed элементами. Значения становятся ключами и предполагают, что - ключи должны быть уникальными в ассоциативных массивах, чтобы не потерялись уникальные значения и конечное число элементов было меньше исходного.

Как сказано в руководстве ключи массива могут быть только типом int или string, так что это то, что вы можете иметь в исходных значениях массива для сравнения, иначе PHP запустит casting с неожиданными результатами.

ДОКАЗАТЕЛЬСТВО ДЛЯ 10-МЕТРОВОЙ ЗАПИСИ

  • Решение с наибольшим количеством голосов: 14.187316179276s ??????????????
  • Принято решение: 2,0736091136932s ??
  • Этот ответ решение: 0,14155888557434s ? / 10

Контрольный пример:

<?php

$elements = array_merge(range(1,10000000),[1]);

$time = microtime(true);
accepted_solution($elements);
echo 'Accepted solution: ', (microtime(true) - $time), 's', PHP_EOL;

$time = microtime(true);
most_voted_solution($elements);
echo 'Most voted solution: ', (microtime(true) - $time), 's', PHP_EOL;

$time = microtime(true);
this_answer_solution($elements);
echo 'This answer solution: ', (microtime(true) - $time), 's', PHP_EOL;

function accepted_solution($array){
 $dupe_array = array();
 foreach($array as $val){
  // sorry, but I had to add below line to remove millions of notices
  if(!isset($dupe_array[$val])){$dupe_array[$val]=0;}
  if(++$dupe_array[$val] > 1){
   return true;
  }
 }
 return false;
}

function most_voted_solution($array) {
   return count($array) !== count(array_unique($array));
}

function this_answer_solution(array $input_array) {
    return count($input_array) === count(array_flip($input_array));
}

Обратите внимание, что принятое решение может быть быстрее в определенных условиях, когда неуникальные значения находятся рядом с началом огромного массива.

37 голосов
/ 30 июня 2010

Вы можете сделать:

function has_dupes($array) {
    $dupe_array = array();
    foreach ($array as $val) {
        if (++$dupe_array[$val] > 1) {
            return true;
        }
    }
    return false;
}
4 голосов
/ 06 марта 2019
$duplicate = false;

 if(count(array) != count(array_unique(array))){
   $duplicate = true;
}
4 голосов
/ 17 февраля 2017
count($array) > count(array_unique($array)); 

Будет false, если дублируется, или true, если нет дубликатов.

4 голосов
/ 08 ноября 2013

Вот мое мнение об этом ... после некоторого бенчмаркинга я обнаружил, что это самый быстрый метод для этого.

function has_duplicates( $array ) {
    return count( array_keys( array_flip( $array ) ) ) !== count( $array );
}

… или в зависимости от обстоятельств это может быть незначительно быстрее.

function has_duplicates( $array ) {
    $array = array_count_values( $array );
    rsort( $array );
    return $array[0] > 1;
}
2 голосов
/ 13 февраля 2012

Говори просто, глупо!;)

Простая логика ИЛИ ...

function checkDuplicatesInArray($array){
    $duplicates=FALSE;
    foreach($array as $k=>$i){
        if(!isset($value_{$i})){
            $value_{$i}=TRUE;
        }
        else{
            $duplicates|=TRUE;          
        }
    }
    return ($duplicates);
}

С уважением!

1 голос
/ 26 февраля 2013

Найдите это полезное решение

function get_duplicates( $array ) {
    return array_unique( array_diff_assoc( $array, array_unique( $array ) ) );
}

После этого подсчета результат, если больше 0, чем дубликаты, в противном случае уникален.

0 голосов
/ 03 февраля 2016

Вы также можете сделать это следующим образом: Это вернет true, если уникальный, иначе вернет false.

$nofollow = (count($modelIdArr) !== count(array_unique($modelIdArr))) ? true : false;
0 голосов
/ 23 марта 2015

Я использую это:

if(count($array)==count(array_count_values($array))){
    echo("all values are unique");
}else{
    echo("there's dupe values");
}

Я не знаю, самый ли это быстрый, но пока работает довольно хорошо

...