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 uniqfungsi dariList::MoreUtils
myleksikal dalam lingkup ini, jadi tidak masalah. Karena itu, mungkin nama variabel yang lebih deskriptif dapat dipilih.
$::adan $::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_listharus ada di dalam uniqpanggilan, 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::MoreUtilsuse 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 %seenatau 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