2008-08-11 11 views

Répondre

145

Vous pouvez faire quelque chose comme ceci comme démontré dans perlfaq4:

sub uniq { 
    my %seen; 
    grep !$seen{$_}++, @_; 
} 

my @array = qw(one two three two three); 
my @filtered = uniq(@array); 

print "@filtered\n"; 

Sorties:

one two three 

Si vous souhaitez utiliser un module, essayez la fonction uniq de List::MoreUtils

+27

s'il vous plaît ne pas utiliser d'un $ ou $ b dans les exemples car ils sont les GLOBALS magiques de sort() – szabgab

+2

Il est un lexique 'my' dans ce portée, donc c'est bien. Cela étant dit, un nom de variable plus descriptif pourrait éventuellement être choisi. – ephemient

+2

@ephemient oui, mais si vous deviez ajouter un tri dans cette fonction, alors il aurait surclassé '$ :: a' et' $ :: b', n'est-ce pas? – vol7ron

20

Mon la façon habituelle de le faire est:

my %unique =(); 
foreach my $item (@myarray) 
{ 
    $unique{$item} ++; 
} 
my @myuniquearray = keys %unique; 

Si vous utilisez un hachage et ajoutez les éléments au hachage. Vous avez également le bonus de savoir combien de fois chaque élément apparaît dans la liste.

+2

Cela a l'inconvénient de ne pas conserver la commande d'origine, si vous en avez besoin. –

+0

Il est préférable d'utiliser [tranches] (http://perldoc.perl.org/perldata.html#Slices) au lieu de foreach' boucle: '@unique {@myarray} =()' – Onlyjob

115

La documentation Perl est livrée avec une belle collection de FAQ. Votre question est souvent posée:

% perldoc -q duplicate 

La réponse, copier et coller à partir de la sortie de la commande ci-dessus, apparaît ci-dessous:

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 # Comment-je-supprimer-dupliquer-des-éléments-d'-une-liste-ou-tableau% 3F – szabgab

+14

John iz dans mah anzers voler mah rep! –

+5

Je pense que vous devriez obtenir des points bonus pour regarder la question. –

63

Installer List::MoreUtils CPAN

Puis dans votre code:

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

Voilà la réponse! Mais je ne peux que vous voter une fois. – Axeman

+3

Le fait que List :: MoreUtils ne soit pas livré avec perl kinda endommage la portabilité des projets qui l'utilisent :((je ne le ferai pas) – yPhil

+3

@Ranguard: '@ dup_list' devrait être dans l'appel' uniq', pas '@ dups' – incutonez

3

Ce dernier était plutôt bon. Je voudrais juste le modifier un peu:

my @arr; 
my @uniqarr; 

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

Je pense que c'est probablement la façon la plus lisible de le faire.

+0

Plus indépendant .. – laki

6

La @array variable est la liste des éléments en double

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

peut être fait avec un simple Perl une doublure.

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. 

Le bloc PFM fait ceci:

données dans @in est introduit dans MAP. MAP crée un hachage anonyme. Les clés sont extraites du hash et alimentées dans @out

0

Essayez ceci, il semble que la fonction uniq nécessite une liste triée pour fonctionner correctement.

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

Utiliser concept de clés de hachage uniques:

my @array = ("a","b","c","b","a","d","c","a","d"); 
my %hash = map { $_ => 1 } @array; 
my @unique = keys %hash; 
print "@unique","\n"; 

Sortie: ACBD

1

Méthode 1: Utiliser un hachage

Logic: Un hachage ne peut avoir que des clés uniques, donc itérer sur le tableau, assigner n'importe quelle valeur à chaque élément du tableau, en gardant l'élément comme clé de ce hachage. Renvoyez les clés du hachage, c'est votre tableau unique.

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

Méthode 2: Extension de la méthode 1 pour réutilisabilité

Mieux vaut faire un sous-programme si nous sommes censés utiliser cette fonctionnalité à plusieurs reprises dans notre code.

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

Méthode 3: Utiliser le module List::MoreUtils

use List::MoreUtils qw(uniq); 
my @unique = uniq(@array); 
Questions connexes