Yanıtlar:
Perlfaq4'te gösterildiği gibi böyle bir şey yapabilirsiniz :
sub uniq {
my %seen;
grep !$seen{$_}++, @_;
}
my @array = qw(one two three two three);
my @filtered = uniq(@array);
print "@filtered\n";
Çıktılar:
one two three
Bir modül kullanmak istiyorsanız uniq
,List::MoreUtils
my
Bu kapsamda bir sözlük, bu yüzden iyi. Bununla birlikte, muhtemelen daha açıklayıcı bir değişken adı seçilebilir.
$::a
ve $::b
değil mi?
sub uniq { my %seen; grep !$seen{$_}++, @_ }
siparişi ücretsiz olarak koruduğundan daha iyi bir uygulamadır. Ya da daha iyisi, List :: MoreUtils'ten birini kullanın.
Perl dokümanları hoş bir SSS koleksiyonu ile birlikte gelir. Sorunuz sık soruluyor:
% perldoc -q duplicate
Yukarıdaki komutun çıktısından cevaplanan, kopyalanan ve yapıştırılan cevap aşağıda görünür:
/Usr/local/lib/perl5/5.10.0/pods/perlfaq4.pod içinde bulundu Bir listeden veya diziden yinelenen öğeleri nasıl kaldırabilirim? (brian d foy tarafından yazılmıştır) Bir karma kullanın. "Benzersiz" veya "çoğaltılmış" kelimelerini düşündüğünüzde, msgstr "hash tuşları". Elemanların sırasını umursamıyorsanız, sadece karma oluşturun ve sonra anahtarları çıkarın. Nasıl olduğun önemli değil bu karmayı yaratın: sadece benzersiz öğeleri almak için "anahtarları" kullanın. % karma = harita {$ _, 1} @array; # veya bir karma dilim: @hash {@array} = (); # veya bir foreach: $ hash {$ _} = 1 foreach (@array); @unique = anahtarlar% kare; Bir modül kullanmak istiyorsanız, "uniq" işlevini "Liste :: MoreUtils". Liste bağlamında benzersiz öğeleri döndürür, Listedeki sıralarını koruyarak. Skaler bağlamda, benzersiz elemanların sayısı. Listeyi kullan :: MoreUtils qw (uniq); benim benzersiz = uniq (1, 2, 3, 4, 4, 5, 6, 5, 7); # 1,2,3,4,5,6,7 $ benzersiz = uniq (1, 2, 3, 4, 4, 5, 6, 5, 7); # 7 Ayrıca her öğeyi gözden geçirebilir ve gördüklerinizi atlayabilirsiniz önce. Takip etmek için bir karma kullanın. Döngü ilk kez bir öğesinde, bu öğenin% Seen içinde anahtarı yok. "Next" ifadesi anahtar ve hemen "undef" değerini kullanır, böylece döngü "itmeye" devam eder ve o tuşun değerini artırır. Sonraki döngü aynı öğeyi gördüğünde, anahtarı karmada bulunur ve bu anahtarın değeri doğrudur (0 veya "undef" olmadığı için) sonraki bu yinelemeyi atlar ve döngü bir sonraki öğeye gider. benim benzersiz = (); % 'mim görüldü = (); (@array) { sonra $ {$ elem} ++ görürse; it @unique, $ elem; } Aynı şeyi bir grep kullanarak daha kısaca yazabilirsiniz. şey. % 'mim görüldü = (); @unique = grep {! $ görüldü {$ _} ++} @array;
Yükleme Listesi :: MoreUtils CPAN
Sonra kodunuzda:
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
içinde olmalı uniq
, değil@dups
Bunu yapmanın olağan yolu:
my %unique = ();
foreach my $item (@myarray)
{
$unique{$item} ++;
}
my @myuniquearray = keys %unique;
Bir karma kullanır ve öğeleri karma öğesine eklerseniz. Ayrıca, her bir öğenin listede kaç kez göründüğünü bilme bonusu da vardır.
Basit bir Perl tek astar ile yapılabilir.
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.
PFM bloğu bunu yapar:
@İn'deki veriler MAP'a beslenir. MAP anonim bir karma oluşturur. Anahtarlar karma'dan çıkarılır ve @out'a beslenir
Mantık: Bir karma yalnızca benzersiz anahtarlara sahip olabilir, bu nedenle dizi üzerinde yineleme yapın, öğeyi bu karma öğesinin anahtarı olarak tutarak dizinin her öğesine herhangi bir değer atayın. Karma anahtarları, benzersiz diziniz.
my @unique = keys {map {$_ => 1} @array};
Bu işlevselliği kodumuzda birden çok kez kullanmamız gerekiyorsa altyordam yapmak daha iyidir.
sub get_unique {
my %seen;
grep !$seen{$_}++, @_;
}
my @unique = get_unique(@array);
List::MoreUtils
use List::MoreUtils qw(uniq);
my @unique = uniq(@array);
Önceki cevaplar bu görevi yerine getirmenin olası yollarını hemen hemen özetliyor.
Ancak, ben olanlar için bir değişiklik önermek yok umurumda sayma çiftleri, ama yapmak amacıyla umurumda.
my @record = qw( yeah I mean uh right right uh yeah so well right I maybe );
my %record;
print grep !$record{$_} && ++$record{$_}, @record;
İhmal edilmeden önce daha önce önerilen grep !$seen{$_}++ ...
artışların olduğuna dikkat edin $seen{$_}
, bu nedenle artış daha önce olup olmadığına bakılmaksızın gerçekleşir %seen
. Bununla birlikte, yukarıdakiler, $record{$_}
doğru olduğunda kısa devreler , duyulanları bir kez 'kapalı' olarak bırakır %record
.
Ayrıca, otomatik doğrulama ve karma anahtarlarının varlığından yararlanan bu saçmalık için de gidebilirsiniz:
...
grep !(exists $record{$_} || undef $record{$_}), @record;
Ancak bu biraz karışıklığa neden olabilir.
Ve ne sipariş ne de yinelenen sayımı önemsiyorsanız, karma dilimleri ve az önce bahsettiğim hileyi kullanarak başka bir kesmek için yapabilirsiniz:
...
undef @record{@record};
keys %record; # your record, now probably scrambled but at least deduped
sub uniq{ my %seen; undef @seen{@_}; keys %seen; }
Temiz.
Bunu deneyin, uniq işlevinin düzgün çalışması için sıralı bir listeye ihtiyacı var gibi görünüyor.
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";
Benzersiz karma anahtar kavramını kullanma:
my @array = ("a","b","c","b","a","d","c","a","d");
my %hash = map { $_ => 1 } @array;
my @unique = keys %hash;
print "@unique","\n";
Çıktı: acbd