Frage

Ich habe ein Array in Perl:

my @my_array = ("one","two","three","two","three");

Wie entferne ich die Duplikate aus dem Array?

War es hilfreich?

Lösung

Sie können so etwas tun, wie in gezeigt perlfaq4:

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, probieren Sie es aus uniq Funktion von List::MoreUtils

Andere Tipps

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

% perldoc -q duplicate

Die Antwort, kopiert und eingefügt aus der Ausgabe des obigen Befehls, erscheint unten:

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;

Installieren List::MoreUtils von CPAN

Dann in Ihrem 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);

Meine übliche Vorgehensweise 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 außerdem den Vorteil, dass Sie wissen, wie oft jedes Element in der Liste vorkommt.

Kann mit einem einfachen Perl-Einzeiler durchgeführt werden.

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 macht Folgendes:

Daten in @in werden in MAP eingespeist.MAP erstellt einen anonymen Hash.Schlüssel werden aus dem Hash extrahiert und in @out eingespeist

Die Variable @array ist die Liste mit doppelten Elementen

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

Das letzte war ziemlich gut.Ich würde es einfach ein wenig anpassen:

my @arr;
my @uniqarr;

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

Ich denke, das ist wahrscheinlich die am besten lesbare Art und Weise, es zu tun.

Methode 1:Verwenden Sie einen Hash

Logik:Ein Hash kann nur eindeutige Schlüssel haben, also iterieren Sie über das Array, weisen Sie jedem Element des Arrays einen beliebigen Wert zu und behalten Sie das Element als Schlüssel dieses Hashs bei.Rückgabeschlüssel des Hashs, es ist Ihr einzigartiges Array.

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

Methode 2:Erweiterung der Methode 1 zur Wiederverwendbarkeit

Wenn wir diese Funktionalität in unserem Code mehrmals verwenden möchten, ist es besser, eine Unterroutine zu erstellen.

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

Methode 3:Modul verwenden List::MoreUtils

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

Frühere Antworten fassen die möglichen Wege zur Lösung dieser Aufgabe ziemlich genau zusammen.

Ich schlage jedoch eine Modifikation für diejenigen vor, die nicht Wert darauf legen Zählen die Duplikate, aber Tun auf Ordnung achten.

my @record = qw( yeah I mean uh right right uh yeah so well right I maybe );
my %record;
print grep !$record{$_} && ++$record{$_}, @record;

Beachten Sie, dass das zuvor vorgeschlagene grep !$seen{$_}++ ... Schritte $seen{$_} vor der Negierung, daher erfolgt die Inkrementierung unabhängig davon, ob sie bereits erfolgt ist %seen oder nicht.Das oben Gesagte führt jedoch zu Kurzschlüssen $record{$_} ist wahr, das Gehörte einmal wegzulassen %record'.

Sie könnten sich auch für diese Lächerlichkeit entscheiden, die sich die Autovivifizierung und die Existenz von Hash-Schlüsseln zunutze macht:

...
grep !(exists $record{$_} || undef $record{$_}), @record;

Das könnte jedoch zu Verwirrung führen.

Und wenn Ihnen weder die Reihenfolge noch die Anzahl der Duplikate wichtig sind, können Sie einen weiteren Hack verwenden, indem Sie Hash-Slices und den Trick verwenden, den ich gerade erwähnt habe:

...
undef @record{@record};
keys %record; # your record, now probably scrambled but at least deduped

Versuchen Sie dies, anscheinend benötigt die Uniq-Funktion eine sortierte Liste, 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";

Verwendung des Konzepts eindeutiger 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";

Ausgabe:a c b d

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top