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 uniq
funkcję zList::MoreUtils
my
tym zakresie jest leksykalny, więc jest w porządku. Biorąc to pod uwagę, prawdopodobnie można wybrać bardziej opisową nazwę zmiennej.
$::a
i $::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_list
powinno być wewnątrz uniq
rozmowy, 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::MoreUtils
use 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ł, %seen
czy 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