2008-08-11 25 views

Antwort

145

Sie können etwas tun, wie in perlfaq4 demonstriert:

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

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

print "@filtered\n"; 

Ausgänge:

one two three 

Wenn Sie ein Modul verwenden möchten, versuchen Sie die uniq Funktion von List::MoreUtils

+27

benutzen Sie bitte $ a oder $ b nicht in den Beispielen, wie sie die magischen Globals der Art sind() – szabgab

+2

Es ist ein 'my' lexikalisch in dieser Umfang, so ist es in Ordnung. Davon abgesehen könnte möglicherweise ein beschreibenderer Variablenname gewählt werden. – ephemient

+2

@ephemient Ja, aber wenn Sie die Sortierung in dieser Funktion hinzufügen würden, würde es '$ :: a' und' $ :: b' trumpfen, oder? – vol7ron

20

Meine Übliche Art dies zu tun ist:

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

Wenn Sie einen Hash verwenden und die Elemente zum Hash hinzufügen. Sie haben auch den Bonus zu wissen, wie oft jedes Element in der Liste angezeigt wird.

+2

Das hat den Nachteil, die ursprüngliche Reihenfolge nicht zu erhalten, wenn Sie sie brauchen. –

+0

Es ist besser, [slices] (http://perldoc.perl.org/perldata.html#Slices) anstelle von 'foreach' zu verwenden:' @unique {@myarray} =() ' – Onlyjob

115

Die Perl-Dokumentation enthält eine schöne Sammlung von FAQs. Ihre Frage wird häufig gestellt:

% perldoc -q duplicate 

Die Antwort, kopieren und aus der Ausgabe des Befehls oben eingefügt, unten erscheint:

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-entfernen-duplicate-elements-from-a-list-or-array% 3F – szabgab

+14

John iz in mah anzers stehlen mah rep! –

+5

Ich denke, du solltest Bonuspunkte bekommen, um die Frage tatsächlich zu stellen. –

63

installieren List::MoreUtils von CPAN

Dann im 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

Das ist die Antwort! Aber ich kann dich nur einmal abstimmen. – Axeman

+3

Die Tatsache, dass List :: MoreUtils nicht mit Perl gebündelt ist, beschädigt die Portabilität von Projekten, die es benutzen :((Ich für den einen werde nicht) – yPhil

+3

@Ranguard: '@ dup_list' sollte innerhalb des' uniq' Anrufs sein, nicht '@ dups' – incutonez

3

Das letzte war ziemlich gut. Ich würde es nur ein wenig zwicken:

Ich denke, das ist wahrscheinlich die beste Möglichkeit, es zu tun.

+0

Mehr unabhängige .. – laki

6

Die Variable @array ist die Liste mit doppelten Elemente

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

Kann mit einem einfachen Perl-Einzeiler erfolgen.

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. 

Der PFM-Block tut dies:

Daten in @in in MAP zugeführt. MAP erstellt einen anonymen Hash. Die Schlüssel werden aus dem Hash extrahiert und in @out eingegeben.

0

Versuchen Sie dies, scheint die uniq-Funktion eine sortierte Liste benötigt, um ordnungsgemäß zu funktionieren.

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

Mit Konzept der eindeutigen Hash-Schlüssel:

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

Output: acbd

1

Methode 1: Verwenden einer Hash-

Logic: Eine Hash nur eindeutige Schlüssel haben, so Iteriere über ein Array, weise jedem Element des Arrays einen beliebigen Wert zu und behalte das Element als Schlüssel für diesen Hash. Geben Sie die Schlüssel des Hashs zurück, es ist Ihr einzigartiges Array.

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

Methode 2: Erweiterung der Methode 1 für Wiederverwertbarkeit

Besser ein Unterprogramm machen, wenn wir diese Funktionalität mehrfach in unserem Code verwenden sollen.

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

Methode 3: Verwenden Modul List::MoreUtils

use List::MoreUtils qw(uniq); 
my @unique = uniq(@array); 
Verwandte Themen