php:检查数组是否有重复项

Mal*_*ala 57 php arrays duplicates

我确信这是一个非常明显的问题,并且有一个函数正是这样做的,但我似乎无法找到它.在PHP中,我想知道我的数组是否有重复,尽可能高效.我不想像它那样删除它们array_unique,我并不特别想运行array_unique并将它与原始数组进行比较,看看它们是否相同,因为这看起来非常低效.就性能而言,"预期条件"是阵列没有重复.

我只是希望能够做类似的事情

if (no_dupes($array))
    // this deals with arrays without duplicates
else
    // this deals with arrays with duplicates
Run Code Online (Sandbox Code Playgroud)

我有没有想到的任何明显的功能?
如何检测PHP数组中的重复值?
有正确的标题,是一个非常相似的问题,但如果你真的读过这个问题,他正在寻找array_count_values.

Jas*_*ary 189

我知道你不是在追求array_unique().但是,你不会找到一个神奇的 明显功能,也不会写一个比使用本机功能更快.

我提议:

function array_has_dupes($array) {
   // streamline per @Felix
   return count($array) !== count(array_unique($array));
}
Run Code Online (Sandbox Code Playgroud)

调整第二个参数array_unique()以满足您的比较需求.

  • 优雅,但`array_unique`有点慢.如果你知道数组只包含整数和字符串,你可以用`array_flip`替换它,以获得更快的结果. (4认同)
  • 谢谢你的建议.我在寻找更好的算法时的想法很简单,从技术上讲,一旦你完成了内置的"array_unique"的运行,你应该能够知道是否有任何欺骗.因此,任何至少与"array_unique"一样工作的东西所做的工作都比必要的要多.虽然是的,如果不存在这样的功能,我并不特别喜欢写它. (3认同)

s3m*_*m3n 53

⚡性能解决方案⚡

如果你关心性能和微观优化,请检查这个单行:

function no_dupes(array $input_array) {
    return count($input_array) === count(array_flip($input_array));
}
Run Code Online (Sandbox Code Playgroud)

描述:

函数$input_array使用array_flip的ed元素比较数组元素的数量.值成为键并猜测 - 键在关联数组中必须是唯一的,因此不会丢失唯一值,并且最终元素数低于原始值.

正如所说手动数组的键可以只类型int或者string所以这是你可以在原来的数组值进行比较,否则PHP将开始铸造有意想不到的效果.

10M记录阵列的证明

  • 最投票的解决方案: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));
}
Run Code Online (Sandbox Code Playgroud)

请注意,当没有唯一值接近大数组的开头时,接受的解决方案在某些条件下可能会更快.

  • @ErdalG。这更快,因为 `array_flip` 是 [用 C 编写的本机 PHP 函数](https://github.com/php/php-src/blob/9426c6e/ext/standard/array.c#L4340) 并且翻转非常简单手术。翻转后,不会删除唯一值,因为它们可能会造成数组键冲突。 (2认同)

Mik*_*rov 38

你可以做:

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

  • 这段代码在PHP中给出了一个"未定义的偏移量"错误.相反,我做了:`foreach($ a as $ v){if(array_key_exists($ v,$ dupe){return true;} else {$ dupe [$ v] = true;}` (9认同)
  • 我喜欢!请记住,即使早期"返回",这也是一个O(n)函数.除了"foreach"的开销和跟踪"$ dupe_array"之外,我还希望看到一些基准测试.我猜对于没有重复的数组,使用本机函数更快.但绝对优于O(n ^ 2).尼斯. (6认同)
  • 这怎么工作?由于`$ dupe_array`尚未定义任何值,`$ dupe_array [$ val]`应返回未定义的索引! (3认同)
  • 有一点问题:只有值是字符串或数字才能正常工作. (2认同)
  • 我在这里看不到好东西,只是一堆通知。 (2认同)

And*_*rew 21

$hasDuplicates = count($array) > count(array_unique($array)); 
Run Code Online (Sandbox Code Playgroud)

将是true如果重复,或者false如果没有重复。


小智 6

$duplicate = false;

 if(count(array) != count(array_unique(array))){
   $duplicate = true;
}
Run Code Online (Sandbox Code Playgroud)


mic*_*lli 5

这是我在进行一些基准测试后对此\xe2\x80\xa6 的看法,我发现这是最快的方法。

\n\n
function has_duplicates( $array ) {\n    return count( array_keys( array_flip( $array ) ) ) !== count( $array );\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

\xe2\x80\xa6or 根据具体情况,这可能会稍微快一些。

\n\n
function has_duplicates( $array ) {\n    $array = array_count_values( $array );\n    rsort( $array );\n    return $array[0] > 1;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

  • 不知道为什么你的答案中需要 `array_keys()` 。如果值相同,则 `array_flip()` 已经压缩了您的数组。另外,“!=”是一个足够的比较器,因为“count()”中的类型本质上是相同的(您是提到基准测试的人)。因此 `return count(array_flip($arr)) != count($arr);` 应该足够了。 (2认同)