Tengo una matriz en Perl:
my @my_array = ("one","two","three","two","three");
¿Cómo elimino los duplicados de la matriz?
perl
arrays
unique
duplicates
David
fuente
fuente

myléxico en este ámbito, por lo que está bien. Dicho esto, posiblemente podría elegirse un nombre de variable más descriptivo.$::ay$::b, ¿no?sub uniq { my %seen; grep !$seen{$_}++, @_ }es una mejor implementación ya que conserva el orden sin costo. O incluso mejor, use el de List :: MoreUtils.La documentación de Perl viene con una buena colección de preguntas frecuentes. Su pregunta se hace con frecuencia:
La respuesta, copiar y pegar de la salida del comando anterior, aparece a continuación:
Encontrado en /usr/local/lib/perl5/5.10.0/pods/perlfaq4.pod ¿Cómo puedo eliminar elementos duplicados de una lista o matriz? (contribuido por brian d foy) Usa un hash. Cuando piense que las palabras son "únicas" o "duplicadas", piense "claves hash". Si no te importa el orden de los elementos, podrías simplemente crea el hash y luego extrae las claves. No importa cómo crea ese hash: solo que usas "claves" para obtener los elementos únicos. my% hash = map {$ _, 1} @array; # o una rebanada hash: @hash {@array} = (); # o un foreach: $ hash {$ _} = 1 foreach (@array); my @unique = keys% hash; Si desea utilizar un módulo, pruebe la función "uniq" de "Lista :: MoreUtils". En el contexto de la lista, devuelve los elementos únicos, preservando su orden en la lista. En contexto escalar, devuelve el Número de elementos únicos. use List :: MoreUtils qw (uniq); my @unique = uniq (1, 2, 3, 4, 4, 5, 6, 5, 7); # 1,2,3,4,5,6,7 my $ unique = uniq (1, 2, 3, 4, 4, 5, 6, 5, 7); # 7 También puede revisar cada elemento y omitir los que ha visto. antes de. Use un hash para realizar un seguimiento. La primera vez que el bucle ve un elemento, ese elemento no tiene clave en% Visto. La declaración "siguiente" crea la clave e inmediatamente usa su valor, que es "undef", por lo que el bucle continúa al "empuje" e incrementa el valor de esa clave. El siguiente cada vez que el bucle ve ese mismo elemento, su clave existe en el hash y el valor para esa clave es verdadero (ya que no es 0 o "undef"), entonces el siguiente omite esa iteración y el bucle va al siguiente elemento. my @unique = (); mi% visto = (); foreach my $ elem (@array) { siguiente si $ visto {$ elem} ++; push @unique, $ elem; } Puedes escribir esto más brevemente usando un grep, que hace lo mismo cosa. mi% visto = (); my @unique = grep {! $ visto {$ _} ++} @array;fuente
Instalar :: listado de MoreUtils desde CPAN
Luego en tu código:
fuente
@dup_listdebería estar dentro de launiqllamada, no@dupsMi forma habitual de hacer esto es:
Si usa un hash y agrega los elementos al hash. También tiene la ventaja de saber cuántas veces aparece cada elemento en la lista.
fuente
foreachbucle:@unique{@myarray}=()La variable @array es la lista con elementos duplicados.
fuente
Se puede hacer con un simple Perl One Liner.
El bloque PFM hace esto:
Los datos en @in se introducen en MAP. MAP crea un hash anónimo. Las claves se extraen del hash y se introducen en @out
fuente
Ese último fue bastante bueno. Solo lo modificaría un poco:
Creo que esta es probablemente la forma más fácil de hacerlo.
fuente
Método 1: usar un hash
Lógica: un hash solo puede tener claves únicas, por lo que iterar sobre la matriz, asignar cualquier valor a cada elemento de la matriz, manteniendo el elemento como clave de ese hash. Teclas de retorno del hash, es su matriz única.
Método 2: extensión del método 1 para reutilización
Es mejor hacer una subrutina si se supone que debemos usar esta funcionalidad varias veces en nuestro código.
Método 3: usar el módulo
List::MoreUtilsfuente
Las respuestas anteriores resumen bastante bien las posibles formas de llevar a cabo esta tarea.
Sin embargo, sugiero una modificación para aquellos a quienes no les importa contar los duplicados, pero sí les importa el orden.
Tenga en cuenta que los
grep !$seen{$_}++ ...incrementos sugeridos anteriormente$seen{$_}antes de negar, por lo que el incremento se produce independientemente de si ya ha sido%seeno no. Lo anterior, sin embargo, hace un cortocircuito cuando$record{$_}es cierto, dejando lo que se escuchó una vez "fuera de%record".También podría optar por esta ridiculez, que aprovecha la autovivificación y la existencia de claves hash:
Eso, sin embargo, podría generar cierta confusión.
Y si no le importa ni el orden ni el recuento duplicado, podría usar otro truco utilizando trozos de hash y el truco que acabo de mencionar:
fuente
sub uniq{ my %seen; undef @seen{@_}; keys %seen; }aseado.Pruebe esto, parece que la función uniq necesita una lista ordenada para funcionar correctamente.
fuente
Usando el concepto de claves hash únicas:
Salida: acbd
fuente