Jawaban:
Anda dapat melakukan sesuatu seperti ini seperti yang ditunjukkan dalam perlfaq4 :
sub uniq {
my %seen;
grep !$seen{$_}++, @_;
}
my @array = qw(one two three two three);
my @filtered = uniq(@array);
print "@filtered\n";
Output:
one two three
Jika Anda ingin menggunakan modul, coba uniq
fungsi dariList::MoreUtils
my
leksikal dalam lingkup ini, jadi tidak masalah. Karena itu, mungkin nama variabel yang lebih deskriptif dapat dipilih.
$::a
dan $::b
, bukan?
sub uniq { my %seen; grep !$seen{$_}++, @_ }
adalah implementasi yang lebih baik karena menjaga ketertiban tanpa biaya. Atau bahkan lebih baik, gunakan yang dari Daftar :: MoreUtils.
Dokumentasi Perl dilengkapi dengan koleksi FAQ yang bagus. Pertanyaan Anda sering diajukan:
% perldoc -q duplicate
Jawaban, salin dan tempel dari output dari perintah di atas, muncul di bawah ini:
Ditemukan di /usr/local/lib/perl5/5.10.0/pods/perlfaq4.pod Bagaimana saya bisa menghapus elemen duplikat dari daftar atau array? (disumbangkan oleh brian d foy) Gunakan hash. Ketika Anda berpikir kata "unik" atau "digandakan", pikirkan "kunci hash". Jika Anda tidak peduli dengan urutan elemen, Anda bisa saja buat hash lalu ekstrak kuncinya. Tidak penting bagaimana Anda buat hash itu: cukup gunakan "kunci" untuk mendapatkan elemen unik. % hash saya = map {$ _, 1} @array; # atau potongan hash: @hash {@array} = (); # atau foreach: $ hash {$ _} = 1 foreach (@array); @unique = kunci saya% hash; Jika Anda ingin menggunakan modul, coba fungsi "uniq" dari "Daftar :: MoreUtils". Dalam konteks daftar itu mengembalikan elemen unik, mempertahankan pesanan mereka dalam daftar. Dalam konteks skalar, ia mengembalikan sejumlah elemen unik. gunakan Daftar :: MoreUtils qw (uniq); myunik = 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 Anda juga dapat menelusuri setiap elemen dan melewati elemen yang telah Anda lihat sebelum. Gunakan hash untuk melacak. Pertama kali loop melihat sebuah elemen, elemen itu tidak memiliki kunci di% Dilihat. Pernyataan "berikutnya" dibuat kunci dan segera menggunakan nilainya, yaitu "undef", jadi loop melanjutkan ke "push" dan menambah nilai untuk kunci itu. Selanjutnya kali loop melihat elemen yang sama, kuncinya ada di hash dan nilai untuk kunci itu benar (karena bukan 0 atau "undef"), jadi selanjutnya melewatkan iterasi dan loop ke elemen berikutnya. @unique saya = (); % saya terlihat = (); foreach my $ elem (@array) { selanjutnya jika $ seen {$ elem} ++; push @unique, $ elem; } Anda dapat menulis ini lebih singkat menggunakan grep, yang melakukan hal yang sama benda. % saya terlihat = (); @unique saya = grep {! $ seen {$ _} ++} @array;
Pasang Daftar :: MoreUtils dari CPAN
Kemudian dalam kode Anda:
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
harus ada di dalam uniq
panggilan, bukan@dups
Cara biasa saya melakukan ini adalah:
my %unique = ();
foreach my $item (@myarray)
{
$unique{$item} ++;
}
my @myuniquearray = keys %unique;
Jika Anda menggunakan hash dan menambahkan item ke hash. Anda juga memiliki bonus untuk mengetahui berapa kali setiap item muncul dalam daftar.
Dapat dilakukan dengan Perl satu liner sederhana.
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 melakukan ini:
Data dalam @in dimasukkan ke dalam MAP. MAP membangun hash anonim. Kunci diekstraksi dari hash dan diumpankan ke @out
Logika: Sebuah hash hanya dapat memiliki kunci unik, jadi iterate over array, tetapkan nilai apa pun untuk setiap elemen array, jadikan elemen sebagai kunci hash itu. Kembalikan kunci hash, ini array unik Anda.
my @unique = keys {map {$_ => 1} @array};
Lebih baik membuat subrutin jika kita seharusnya menggunakan fungsi ini beberapa kali dalam kode kita.
sub get_unique {
my %seen;
grep !$seen{$_}++, @_;
}
my @unique = get_unique(@array);
List::MoreUtils
use List::MoreUtils qw(uniq);
my @unique = uniq(@array);
Jawaban sebelumnya cukup meringkas cara yang mungkin untuk menyelesaikan tugas ini.
Namun, saya menyarankan modifikasi bagi mereka yang tidak peduli tentang menghitung duplikat, tetapi melakukan perawatan tentang pesanan.
my @record = qw( yeah I mean uh right right uh yeah so well right I maybe );
my %record;
print grep !$record{$_} && ++$record{$_}, @record;
Perhatikan bahwa grep !$seen{$_}++ ...
kenaikan yang disarankan sebelumnya $seen{$_}
sebelum dinegasikan, sehingga peningkatan terjadi terlepas dari apakah sudah %seen
atau belum. Di atas, bagaimanapun, korsleting ketika $record{$_}
benar, meninggalkan apa yang terdengar sekali dari%record
'.
Anda juga bisa menggunakan kekonyolan ini, yang memanfaatkan autovivifikasi dan keberadaan kunci hash:
...
grep !(exists $record{$_} || undef $record{$_}), @record;
Namun, itu bisa menimbulkan kebingungan.
Dan jika Anda tidak peduli dengan urutan atau jumlah duplikat, Anda dapat melakukan retasan menggunakan irisan hash dan trik yang baru saja saya sebutkan:
...
undef @record{@record};
keys %record; # your record, now probably scrambled but at least deduped
sub uniq{ my %seen; undef @seen{@_}; keys %seen; }
Rapi.
Coba ini, sepertinya fungsi uniq membutuhkan daftar yang diurutkan untuk berfungsi dengan baik.
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";
Menggunakan konsep kunci hash yang unik:
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