2008-08-11 16 views

Respuesta

145

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 utilizar un módulo, tratan la función uniq de List::MoreUtils

+27

favor, no use $ ao $ b en los ejemplos, ya que son las variables globales mágicos de sort() – szabgab

+2

Es un 'léxica my' en este alcance, así que está bien. Dicho esto, posiblemente se podría elegir un nombre de variable más descriptivo. – ephemient

+2

@ephemient sí, pero si añadieras ordenar en esta función, prevalecería '$ :: a' y' $ :: b', ¿no? – vol7ron

20

Mi La forma habitual de hacerlo 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.

+2

Esto tiene la desventaja de no preservar el orden original, si lo necesita. –

+0

Es mejor usar [sectores] (http://perldoc.perl.org/perldata.html#Slices) en lugar de 'foreach' loop:' @unique {@myarray} =() ' – Onlyjob

115

La documentación de Perl viene con una buena colección de preguntas frecuentes. con frecuencia se le pide a su pregunta:

% perldoc -q duplicate 

La respuesta, copiar y pegar desde la salida del comando anterior, aparece a continuación:

Found in /usr/local/lib/perl5/5.10.0/pods/perlfaq4.pod 
How can I remove duplicate elements from a list or array? 
    (contributed by brian d foy) 

    Use a hash. When you think the words "unique" or "duplicated", think 
    "hash keys". 

    If you don't care about the order of the elements, you could just 
    create the hash then extract the keys. It's not important how you 
    create that hash: just that you use "keys" to get the unique elements. 

     my %hash = map { $_, 1 } @array; 
     # or a hash slice: @hash{ @array } =(); 
     # or a foreach: $hash{$_} = 1 foreach (@array); 

     my @unique = keys %hash; 

    If you want to use a module, try the "uniq" function from 
    "List::MoreUtils". In list context it returns the unique elements, 
    preserving their order in the list. In scalar context, it returns the 
    number of unique elements. 

     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 

    You can also go through each element and skip the ones you've seen 
    before. Use a hash to keep track. The first time the loop sees an 
    element, that element has no key in %Seen. The "next" statement creates 
    the key and immediately uses its value, which is "undef", so the loop 
    continues to the "push" and increments the value for that key. The next 
    time the loop sees that same element, its key exists in the hash and 
    the value for that key is true (since it's not 0 or "undef"), so the 
    next skips that iteration and the loop goes to the next element. 

     my @unique =(); 
     my %seen =(); 

     foreach my $elem (@array) 
     { 
     next if $seen{ $elem }++; 
     push @unique, $elem; 
     } 

    You can write this more briefly using a grep, which does the same 
    thing. 

     my %seen =(); 
     my @unique = grep { ! $seen{ $_ }++ } @array; 
+0

http: // perldoc .perl.org/perlfaq4.html # How-can-I-remove-duplicate-elements-from-a-list-or-array% 3F – szabgab

+14

John iz in mah anzers robo mah rep! –

+5

Creo que deberías obtener puntos de bonificación por realmente buscar la pregunta. –

63

Instalar List::MoreUtils de CPAN

Luego en el 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); 
+2

¡Esa es la respuesta! Pero solo puedo votarte una vez. – Axeman

+3

El hecho de que List :: MoreUtils no esté incluido w/perl daña un poco la portabilidad de los proyectos que lo usan :((I para uno no) – yPhil

+3

@Ranguard: '@ dup_list' debe estar dentro de la llamada' uniq', no '@ dups' – incutonez

3

La última fue bastante buena. Lo retocaré un poco:

my @arr; 
my @uniqarr; 

foreach my $var (@arr){ 
    if (! grep(/$var/, @uniqarr)){ 
    push(@uniqarr, $var); 
    } 
} 

Creo que esta es probablemente la forma más legible de hacerlo.

+0

Más independiente .. – laki

6

El @array variable es la lista con los elementos duplicados

%seen=(); 
@unique = grep { ! $seen{$_} ++ } @array; 
5

Puede ser hecho con un simple Perl un trazador de líneas.

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:

de datos en @in se introduce en MAP. MAP crea un hash anónimo. Las claves se extraen del hash y se introducen en @out

0

Pruebe esto, parece que la función uniq necesita una lista ordenada para que funcione 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"; 
1

Usando concepto de claves hash únicos:

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

1

Método 1: Utilizar un hash

lógica: Un hash sólo puede tener claves únicas, por lo iterar sobre la matriz, asignar cualquier valor a cada elemento de la matriz, manteniendo el elemento como la clave de esa almohadilla. Devuelve las claves del hash, es tu matriz única.

my @unique = keys {map {$_ => 1} @array}; 

Método 2: Extensión del método 1 para la reutilización

mejor hacer una subrutina si se supone que debemos utilizar esta funcionalidad varias veces en nuestro código.

sub get_unique { 
    my %seen; 
    grep !$seen{$_}++, @_; 
} 
my @unique = get_unique(@array); 

Método 3: Utilice el módulo List::MoreUtils

use List::MoreUtils qw(uniq); 
my @unique = uniq(@array); 
Cuestiones relacionadas