2010-06-29 10 views
40

Estoy seguro de que esta es una pregunta extremadamente obvia, y que hay una función que hace exactamente esto, pero parece que no puedo encontrarlo. En PHP, me gustaría saber si mi matriz tiene duplicados, lo más eficientemente posible. No quiero eliminarlos como array_unique, y no quiero particularmente ejecutar array_unique y compararlo con la matriz original para ver si son iguales, ya que esto parece muy ineficiente. En lo que respecta al rendimiento, la "condición esperada" es que la matriz no tenga duplicados.php: comprueba si una matriz tiene duplicados

sólo me gustaría ser capaz de hacer algo como

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

¿Hay alguna función obvia que no estoy pensando?
How to detect duplicate values in PHP array?
tiene el título correcto, y es una pregunta muy similar, sin embargo, si realmente lees la pregunta, está buscando los valores de la cuenta de la matriz.

+0

¿Desea saber si hay duplicados o la cantidad y el valor de dichos duplicados, etc.? –

+1

Solo necesito saber si hay duplicados. Devolver un booleano es perfecto. – Mala

+16

Honestamente, creo que 'if (count ($ array) == count (array_unique ($ array)))' es lo mejor que puedes obtener. Tienes que recorrer la matriz de una forma u otra y creo que el built-in está optimizado para eso. 'array_flip' podría considerarse también. –

Respuesta

31

que puede hacer:

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

¿Dónde se define '$ dupe_array'? ¿No debería definirlo primero para evitar advertencias? – alex

+1

Está implícitamente definido, pero editaré la respuesta para mayor claridad. –

+0

Gracias, esto es lo que tenía en mente :) – Mala

0

dos maneras de hacerlo de manera eficiente que se me ocurre:

  1. insertar todos los valores en una especie de tabla hash y comprobar si el valor que está insertando ya está en ella (O esperado (n) tiempo y o (n) el espacio)

  2. la clasificación de la matriz y a continuación, comprobar si las células adyacentes son iguales (o (nlogn tiempo) y o (1) o o (n) el espacio en función del algoritmo de clasificación)

La solución de stormdrain probablemente sería O (n^2), al igual que cualquier solución que implique escanear el conjunto para cada elemento que busque un duplicado

157

Sé que no está interesado en array_unique(). Sin embargo, no encontrará una función mágicaobvia ni escribir una será más rápido que hacer uso de las funciones nativas.

propongo:

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

Ajuste el segundo parámetro de array_unique() para satisfacer sus necesidades de comparación.

+3

gracias por la sugerencia. Mi idea para encontrar un algoritmo mejor es simplemente que, técnicamente hablando, una vez que hayas terminado de ejecutar lo que sea el '' array_unique' integrado, deberías poder saber si hubo algún truco. Por lo tanto, cualquier cosa que haga al menos tanto trabajo como 'array_unique' hace más trabajo de lo necesario. Aunque sí, si tal función no existe, particularmente no tengo ganas de escribirla. – Mala

+1

Si solo te importa si tiene engaños, entonces eso es lo que haría. Si le importa algo más que si tiene engaños, entonces tiene razón, lo anterior puede hacer más trabajo de lo que necesita. Todo lo que escribas va a ser O (n^2). Incluso si rescatas temprano. Como dijiste, no es común que tengas engaños. Entonces, ¿vale la pena tu tiempo para hacer algo mágico? –

+0

¿Mágico? Claro que es una microoptimización, pero no es "mágico" escribir su propia función, y no estoy seguro de que una solución mejor sea mucho más difícil de escribir que esto. –

0

Como dijimos específicamente que no desea utilizar array_unique Voy a ignorar las otras respuestas a pesar del hecho de que son probablemente mejor.

¿Por qué no usa array_count_values() y luego verifica si la matriz resultante tiene algún valor mayor que 1?

2

¡Manténgalo simple, tonto! ;)

simple lógica OR ...

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

Saludos!

+2

#BadCode - Las mejores maneras de hacer esta comprobación con las funciones de PHP en sí. – FabianoLothor

1

Encontrar esta solución útil

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

Después de eso resultado de la cuenta si es mayor que 0 que duplicados otra cosa única.

3

Aquí está mi opinión sobre esto ... después de una evaluación comparativa, encontré que este es el método más rápido para esto.

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

... o según las circunstancias esto podría ser marginalmente más rápido.

function has_duplicates($array) { 
    $array = array_count_values($array); 
    rsort($array); 
    return $array[0] > 1; 
} 
+2

No estoy seguro de por qué necesita 'array_keys()' en su respuesta. 'array_flip()' ya condensa su matriz si los valores son los mismos. Además, '! =' Es un comparador suficiente, ya que los tipos son intrínsecamente los mismos de 'count()' (usted es el que mencionó el benchmarking). Por lo tanto, 'return count (array_flip ($ arr))! = Count ($ arr);' debería ser suficiente. – cartbeforehorse

0

estoy usando esto:

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

no sé si es el más rápido, pero funciona bastante bien por lo ahora

0

Puede hacerlo así también: Esto devolverá true si es único else devuelve falso.

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

Will be false si duplicados, o true si no hay duplicados.

22

SOLUCIÓN ⚡ RENDIMIENTO ⚡

Si se preocupan por el rendimiento y la micro-optimizaciones mira esto de una sola línea:

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

Descripción:

función compara el número de elementos de matriz en $input_array con array_flip elementos ed. Los valores se convierten en claves y adivinen qué: las claves deben ser únicas en las matrices asociativas, de modo que no se pierdan valores únicos y el número final de elementos sea inferior al original.

Como se ha dicho en manual claves de matriz puede ser único tipo de int o string así que esto es lo que puede tener en los valores originales de la matriz para comparar, de lo contrario comenzará a PHP casting con resultados inesperados.

PRUEBA DE REGISTROS 10M ARRAY

  • Solución más votado: 14.187316179276s
  • solución aceptado: 2.0736091136932s
  • Esta solución respuesta: 0.14155888557434s/10

caso de prueba:

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

Observe que la solución aceptada puede ser más rápida en ciertas condiciones cuando los valores no únicos están cerca del comienzo de una gran matriz.

+0

¿Funcionará solo en el caso en que los valores de matriz no sean objetos? –

+0

Sí, eso es correcto. Se agregó un párrafo para que sea obvio, las teclas de matriz pueden ser solo 'int' o' string', por lo que deben ser tus valores en la matriz para comparar. – s3m3n

Cuestiones relacionadas