Я уверен, что это очень очевидный вопрос, и что есть функция, которая делает именно это, но я не могу найти ее. В 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 начнет кастинг с неожиданными результатами.
Прецедент:
<?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, чем дубликаты, уникальные.
Два способа сделать это эффективно, о чем я могу думать:
вставляя все значения в какую-либо хэш-таблицу и проверяя, находится ли в ней уже введенное значение (ожидаемое время O (n) и O (n))
сортировка массива и проверка того, являются ли соседние ячейки равными (время 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;