values - php: comprueba si una matriz tiene duplicados
unique multidim array php (12)
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 lo hace array_unique
, y particularmente no quiero ejecutar array_unique
y compararlo con el arreglo 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.
Me gustaría poder 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 en la que no estoy pensando?
¿Cómo detectar valores duplicados en 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.
⚡ SOLUCIÓN DE RENDIMIENTO ⚡
Si le interesan el rendimiento y las micro-optimizaciones, consulte este one-liner:
function no_dupes(array $input_array) {
return count($input_array) === count(array_flip($input_array));
}
Descripción:
La función compara el número de elementos de la matriz en $input_array
con elementos de array_flip ''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 dijo en manual teclas de arreglos manual puede haber solo un tipo de int
o string
así que esto es lo que puede tener en los valores de matriz originales para comparar, de lo contrario, PHP comenzará a casting con resultados inesperados.
PRUEBA PARA 10M REGISTROS ARRAY
- La solución más votada: 14.187316179276s 🐌🐌🐌🐌🐌🐌🐌🐌🐌🐌🐌🐌🐌🐌
- Solución aceptada: 2.0736091136932s 🐌🐌
- Esta solución de 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));
}
Tenga en cuenta 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.
¡Mantenlo simple, tonto! ;)
Simple OR lógica ...
function checkDuplicatesInArray($array){
$duplicates=FALSE;
foreach($array as $k=>$i){
if(!isset($value_{$i})){
$value_{$i}=TRUE;
}
else{
$duplicates|=TRUE;
}
}
return ($duplicates);
}
¡Saludos!
Aquí está mi opinión sobre esto ... después de algunos benchmarking, 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 dependiendo de 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;
}
Como dijiste específicamente que no querías usar array_unique
, voy a ignorar las otras respuestas a pesar de que probablemente sean mejores.
¿Por qué no usa array_count_values() y luego verifica si la matriz resultante tiene algún valor mayor que 1?
Dos formas de hacerlo de manera eficiente que puedo pensar:
insertando todos los valores en algún tipo de hashtable y verificando si el valor que estás insertando ya está en él (tiempo O (n) esperado y espacio O (n))
ordenar la matriz y luego verificar si las celdas adyacentes son iguales (O (nlogn) time y O (1) u O (n) espacio dependiendo 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 la matriz para cada elemento en busca de un duplicado
Encuentra esta solución útil
function get_duplicates( $array ) {
return array_unique( array_diff_assoc( $array, array_unique( $array ) ) );
}
Después de ese conteo, el resultado es mayor que 0 que los duplicados únicos.
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 hasta ahora
Php tiene una función para contar las ocurrencias en la matriz array_count_values()
Sé que no estás detrás de array_unique()
. Sin embargo, no encontrarás una función obvia mágica ni escribir 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.
También puedes hacerlo de esa manera: Esto devolverá true si es único else devuelve falso.
$nofollow = (count($modelIdArr) !== count(array_unique($modelIdArr))) ? true : false;
Tu puedes hacer:
function has_dupes($array) {
$dupe_array = array();
foreach ($array as $val) {
if (++$dupe_array[$val] > 1) {
return true;
}
}
return false;
}
count($array) > count(array_unique($array));
Será false
si está duplicado o true
si no hay duplicados.