php: проверьте, имеет ли массив дубликаты

Я уверен, что это очень очевидный вопрос, и что есть функция, которая делает именно это, но я не могу найти ее. В 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.

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

 function has_dupes($array) { $dupe_array = array(); foreach ($array as $val) { if (++$dupe_array[$val] > 1) { return true; } } return false; } 

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

Я предлагаю:

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

Отрегулируйте второй параметр array_unique() чтобы удовлетворить ваши потребности в сравнении.

⚡ РЕШЕНИЕ ПРОИЗВОДИТЕЛЬНОСТИ ⚡

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

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

Описание:

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

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

ДОКАЗАТЕЛЬСТВО ДЛЯ МАРКИРОВКИ

  • Самое голосованое решение: 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)); } 

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

Вот мое взятие этого … после некоторого бенчмаркинга я нашел, что это самый быстрый метод для этого.

 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; } 

Держите его простым, глупым! 😉

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

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

С уважением!

 count($array) > count(array_unique($array)); 

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

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

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

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

Два способа сделать это эффективно, о чем я могу думать:

  1. вставляя все значения в какую-либо хэш-таблицу и проверяя, находится ли в ней уже введенное значение (ожидаемое время O (n) и O (n))

  2. сортировка массива и проверка того, являются ли соседние ячейки равными (время O (nlogn) и O (1) или O (n) в зависимости от алгоритма сортировки)

решение stormdrain, вероятно, будет O (n ^ 2), как и любое решение, которое включает в себя сканирование массива для каждого элемента, ищущего дубликат

Поскольку вы специально сказали, что не хотите использовать array_unique я проигнорирую другие ответы, несмотря на то, что они, вероятно, лучше.

Почему бы вам не использовать array_count_values ​​(), а затем проверить, имеет ли результирующий массив значение больше 1?

Php имеет функцию для подсчета вхождений в массиве http://www.php.net/manual/en/function.array-count-values.php

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

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

Я не знаю, является ли это самым быстрым, но работает очень хорошо

Вы также можете сделать это так: это вернет true, если уникальное else вернет false.

 $nofollow = (count($modelIdArr) !== count(array_unique($modelIdArr))) ? true : false;