Odpowiedzi:
Możesz zrobić coś takiego, jak pokazano w perlfaq4 :
sub uniq {
my %seen;
grep !$seen{$_}++, @_;
}
my @array = qw(one two three two three);
my @filtered = uniq(@array);
print "@filtered\n";
Wyjścia:
one two three
Jeśli chcesz użyć modułu, wypróbuj uniqfunkcję zList::MoreUtils
mytym zakresie jest leksykalny, więc jest w porządku. Biorąc to pod uwagę, prawdopodobnie można wybrać bardziej opisową nazwę zmiennej.
$::ai $::b, prawda?
sub uniq { my %seen; grep !$seen{$_}++, @_ }jest lepszą implementacją, ponieważ zachowuje porządek bez żadnych kosztów. Lub jeszcze lepiej, użyj tego z List :: MoreUtils.
Dokumentacja Perla zawiera niezłą kolekcję często zadawanych pytań. Twoje pytanie jest często zadawane:
% perldoc -q duplicate
Odpowiedź, skopiuj i wklej z wyniku powyższego polecenia, pojawia się poniżej:
Znaleziono w /usr/local/lib/perl5/5.10.0/pods/perlfaq4.pod
Jak mogę usunąć zduplikowane elementy z listy lub tablicy?
(nadesłał brian d foy)
Użyj skrótu. Kiedy myślisz, że słowa „niepowtarzalny” lub „zduplikowany”, pomyśl
„klucze skrótu”.
Jeśli nie zależy Ci na kolejności elementów, możesz po prostu
utwórz skrót, a następnie wyodrębnij klucze. Nie jest ważne, jak ty
stwórz ten hash: wystarczy, że używasz „kluczy”, aby uzyskać unikalne elementy.
mój% hash = map {$ _, 1} @array;
# lub krzyżyk: @hash {@array} = ();
# lub foreach: $ hash {$ _} = 1 foreach (@array);
my @unique = klucze% hash;
Jeśli chcesz użyć modułu, wypróbuj funkcję „uniq” z
„List :: MoreUtils”. W kontekście listowym zwraca unikalne elementy,
zachowanie ich kolejności na liście. W kontekście skalarnym zwraca
liczba unikalnych elementów.
użyj 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
Możesz także przejść przez każdy element i pominąć te, które widziałeś
przed. Użyj skrótu, aby śledzić. Za pierwszym razem, gdy pętla napotka plik
element, ten element nie ma klucza w% Seen. Tworzy instrukcja „next”
klucz i natychmiast używa jego wartości, czyli „undef”, czyli pętli
kontynuuje do „wypychania” i zwiększa wartość tego klucza. Następny
gdy pętla widzi ten sam element, jego klucz istnieje w skrócie i
wartość tego klucza to prawda (ponieważ nie jest to 0 ani „undef”), więc
next pomija tę iterację i pętla przechodzi do następnego elementu.
my @unique = ();
mój% widziany = ();
foreach my $ elem (@array)
{
następny jeśli $ widziany {$ elem} ++;
push @unique, $ elem;
}
Możesz napisać to krócej, używając polecenia grep, co robi to samo
rzecz.
mój% widziany = ();
my @unique = grep {! $ widziano {$ _} ++} @array;
Lista instalacji :: MoreUtils z CPAN
Następnie w swoim kodzie:
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_listpowinno być wewnątrz uniqrozmowy, a nie@dups
Mój zwykły sposób to:
my %unique = ();
foreach my $item (@myarray)
{
$unique{$item} ++;
}
my @myuniquearray = keys %unique;
Jeśli używasz hasha i dodajesz elementy do hasha. Masz również bonus, wiedząc, ile razy każdy element pojawia się na liście.
Można to zrobić za pomocą prostego jednego wkładu Perl.
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.
Blok PFM robi to:
Dane w @in są wprowadzane do MAP. MAP buduje anonimowy hash. Klucze są wyodrębniane z skrótu i przesyłane do @out
Logika: Hash może mieć tylko unikalne klucze, więc iteruj po tablicy, przypisz dowolną wartość do każdego elementu tablicy, zachowując element jako klucz tego skrótu. Klucze zwrotne skrótu, to twoja unikalna tablica.
my @unique = keys {map {$_ => 1} @array};
Lepiej zrobić podprogram, jeśli mamy używać tej funkcji wiele razy w naszym kodzie.
sub get_unique {
my %seen;
grep !$seen{$_}++, @_;
}
my @unique = get_unique(@array);
List::MoreUtilsuse List::MoreUtils qw(uniq);
my @unique = uniq(@array);
Poprzednie odpowiedzi w dużym stopniu podsumowują możliwe sposoby wykonania tego zadania.
Jednak proponuję modyfikację dla tych, którzy nie dbają o liczenie duplikaty, ale zrobić dbają o zamówieniu.
my @record = qw( yeah I mean uh right right uh yeah so well right I maybe );
my %record;
print grep !$record{$_} && ++$record{$_}, @record;
Zwróć uwagę, że poprzednio sugerowane grep !$seen{$_}++ ...przyrosty $seen{$_}przed zaprzeczeniem, więc przyrost zachodzi niezależnie od tego, czy już był, %seenczy nie. Powyższe jednak $record{$_}powoduje zwarcia, gdy jest prawdą, pozostawiając to, co kiedyś usłyszano %record.
Możesz też pójść na tę śmieszność, która wykorzystuje autowifikację i istnienie kluczy mieszających:
...
grep !(exists $record{$_} || undef $record{$_}), @record;
Może to jednak prowadzić do pewnego zamieszania.
A jeśli nie obchodzi Cię ani kolejność, ani liczba duplikatów, możesz zrobić kolejny hack za pomocą plastrów z krzyżykiem i sztuczki, o której wspomniałem:
...
undef @record{@record};
keys %record; # your record, now probably scrambled but at least deduped
sub uniq{ my %seen; undef @seen{@_}; keys %seen; } schludnie.
Spróbuj tego, wygląda na to, że funkcja uniq wymaga posortowanej listy, aby działać poprawnie.
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";
Korzystanie z koncepcji unikalnych kluczy skrótu:
my @array = ("a","b","c","b","a","d","c","a","d");
my %hash = map { $_ => 1 } @array;
my @unique = keys %hash;
print "@unique","\n";
Wyjście: acbd