Respuestas:
Puede hacer algo como esto como se demuestra en perlfaq4 :
sub uniq {
my %seen;
grep !$seen{$_}++, @_;
}
my @array = qw(one two three two three);
my @filtered = uniq(@array);
print "@filtered\n";
Salidas:
one two three
Si desea usar un módulo, pruebe la uniq
función deList::MoreUtils
my
léxico en este ámbito, por lo que está bien. Dicho esto, posiblemente podría elegirse un nombre de variable más descriptivo.
$::a
y $::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:
% perldoc -q duplicate
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;
Instalar :: listado de MoreUtils desde CPAN
Luego en tu código:
use strict;
use warnings;
use List::MoreUtils qw(uniq);
my @dup_list = qw(1 1 1 2 3 4 4);
my @uniq_list = uniq(@dup_list);
@dup_list
debería estar dentro de la uniq
llamada, no@dups
Mi forma habitual de hacer esto es:
my %unique = ();
foreach my $item (@myarray)
{
$unique{$item} ++;
}
my @myuniquearray = keys %unique;
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.
Se puede hacer con un simple Perl One Liner.
my @in=qw(1 3 4 6 2 4 3 2 6 3 2 3 4 4 3 2 5 5 32 3); #Sample data
my @out=keys %{{ map{$_=>1}@in}}; # Perform PFM
print join ' ', sort{$a<=>$b} @out;# Print data back out sorted and in order.
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
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.
my @unique = keys {map {$_ => 1} @array};
Es mejor hacer una subrutina si se supone que debemos usar esta funcionalidad varias veces en nuestro código.
sub get_unique {
my %seen;
grep !$seen{$_}++, @_;
}
my @unique = get_unique(@array);
List::MoreUtils
use List::MoreUtils qw(uniq);
my @unique = uniq(@array);
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.
my @record = qw( yeah I mean uh right right uh yeah so well right I maybe );
my %record;
print grep !$record{$_} && ++$record{$_}, @record;
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 %seen
o 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:
...
grep !(exists $record{$_} || undef $record{$_}), @record;
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:
...
undef @record{@record};
keys %record; # your record, now probably scrambled but at least deduped
sub uniq{ my %seen; undef @seen{@_}; keys %seen; }
aseado.
Pruebe esto, parece que la función uniq necesita una lista ordenada para funcionar correctamente.
use strict;
# Helper function to remove duplicates in a list.
sub uniq {
my %seen;
grep !$seen{$_}++, @_;
}
my @teststrings = ("one", "two", "three", "one");
my @filtered = uniq @teststrings;
print "uniq: @filtered\n";
my @sorted = sort @teststrings;
print "sort: @sorted\n";
my @sortedfiltered = uniq sort @teststrings;
print "uniq sort : @sortedfiltered\n";
Usando el concepto de claves hash únicas:
my @array = ("a","b","c","b","a","d","c","a","d");
my %hash = map { $_ => 1 } @array;
my @unique = keys %hash;
print "@unique","\n";
Salida: acbd