2008-08-11 56 views

Trả lời

145

Bạn có thể làm một cái gì đó như thế này như thể hiện trong perlfaq4:

sub uniq { 
    my %seen; 
    grep !$seen{$_}++, @_; 
} 

my @array = qw(one two three two three); 
my @filtered = uniq(@array); 

print "@filtered\n"; 

Đầu ra:

one two three 

Nếu bạn muốn sử dụng một mô-đun, hãy thử các uniq chức năng từ List::MoreUtils

+27

xin đừng sử dụng $ a hoặc $ b trong các ví dụ như họ là những globals kỳ diệu của sort() – szabgab

+2

Đó là một 'từ vựng my' trong này phạm vi, vì vậy nó là tốt. Điều đó đang được nói, có thể là một tên biến mô tả hơn có thể được chọn. – ephemient

+2

@ephemient yes, nhưng nếu bạn đã thêm phân loại trong hàm này thì nó sẽ vượt trội '$ :: a' và' $ :: b', phải không? – vol7ron

20

My cách thông thường để thực hiện việc này là:

my %unique =(); 
foreach my $item (@myarray) 
{ 
    $unique{$item} ++; 
} 
my @myuniquearray = keys %unique; 

Nếu bạn sử dụng băm và thêm các mục vào băm. Bạn cũng có tiền thưởng khi biết số lần mỗi mục xuất hiện trong danh sách.

+2

Điều này có nhược điểm của việc không bảo quản thứ tự ban đầu, nếu bạn cần nó. –

+0

Tốt hơn nên sử dụng [slice] (http://perldoc.perl.org/perldata.html#Slices) thay vì vòng lặp 'foreach':' @unique {@myarray} =() ' – Onlyjob

115

Tài liệu Perl đi kèm với bộ sưu tập Câu hỏi thường gặp thú vị. Câu hỏi của bạn được hỏi thường gặp:

% perldoc -q duplicate 

Câu trả lời, sao chép và dán từ đầu ra của lệnh trên, xuất hiện bên dưới:

Found in /usr/local/lib/perl5/5.10.0/pods/perlfaq4.pod 
How can I remove duplicate elements from a list or array? 
    (contributed by brian d foy) 

    Use a hash. When you think the words "unique" or "duplicated", think 
    "hash keys". 

    If you don't care about the order of the elements, you could just 
    create the hash then extract the keys. It's not important how you 
    create that hash: just that you use "keys" to get the unique elements. 

     my %hash = map { $_, 1 } @array; 
     # or a hash slice: @hash{ @array } =(); 
     # or a foreach: $hash{$_} = 1 foreach (@array); 

     my @unique = keys %hash; 

    If you want to use a module, try the "uniq" function from 
    "List::MoreUtils". In list context it returns the unique elements, 
    preserving their order in the list. In scalar context, it returns the 
    number of unique elements. 

     use 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 

    You can also go through each element and skip the ones you've seen 
    before. Use a hash to keep track. The first time the loop sees an 
    element, that element has no key in %Seen. The "next" statement creates 
    the key and immediately uses its value, which is "undef", so the loop 
    continues to the "push" and increments the value for that key. The next 
    time the loop sees that same element, its key exists in the hash and 
    the value for that key is true (since it's not 0 or "undef"), so the 
    next skips that iteration and the loop goes to the next element. 

     my @unique =(); 
     my %seen =(); 

     foreach my $elem (@array) 
     { 
     next if $seen{ $elem }++; 
     push @unique, $elem; 
     } 

    You can write this more briefly using a grep, which does the same 
    thing. 

     my %seen =(); 
     my @unique = grep { ! $seen{ $_ }++ } @array; 
+0

http: // perldoc .perl.org/perlfaq4.html # Làm thế nào có thể-tôi-loại bỏ-trùng lặp-yếu tố-từ-một-danh sách-hoặc-mảng% 3F – szabgab

+14

John iz trong mah anzers ăn cắp mah rep! –

+5

Tôi nghĩ bạn nên nhận điểm thưởng để thực sự tìm kiếm câu hỏi. –

63

Install List::MoreUtils từ CPAN

Sau đó, trong mã của bạn:

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); 
+2

Đó là câu trả lời! Nhưng tôi chỉ có thể bầu bạn một lần. – Axeman

+3

Thực tế là Danh sách :: MoreUtils không được đóng gói w/perl kinda gây thiệt hại cho tính di động của các dự án sử dụng nó: ((Tôi không cho) – yPhil

+3

@Phần tử: '@ dup_list' phải nằm trong lệnh gọi' uniq', chứ không phải '@ dups' – incutonez

3

Điều cuối cùng là khá tốt. Tôi chỉ chỉnh sửa một chút:

my @arr; 
my @uniqarr; 

foreach my $var (@arr){ 
    if (! grep(/$var/, @uniqarr)){ 
    push(@uniqarr, $var); 
    } 
} 

Tôi nghĩ đây có lẽ là cách dễ đọc nhất để thực hiện.

+0

Độc lập hơn .. – laki

6

Biến @array là danh sách với các yếu tố trùng lặp

%seen=(); 
@unique = grep { ! $seen{$_} ++ } @array; 
5

có thể được thực hiện với một đơn giản Perl lót.

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. 

Khối PFM thực hiện điều này:

dữ liệu trong @in được đưa vào MAP. MAP xây dựng một băm vô danh. Các khóa được trích xuất từ ​​hàm băm và nguồn cấp dữ liệu vào @out

0

Hãy thử điều này, dường như hàm uniq cần danh sách được sắp xếp để hoạt động bình thường.

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"; 
1

Sử dụng khái niệm về phím băm duy nhất:

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

1

Phương pháp 1: Sử dụng một hash

Logic: Một băm có thể chỉ có phím độc đáo, vì vậy lặp qua mảng, gán bất kỳ giá trị nào cho mỗi phần tử của mảng, giữ nguyên tố làm khóa của băm đó. Phím trả về của băm, mảng duy nhất của nó.

my @unique = keys {map {$_ => 1} @array}; 

Cách 2: mở rộng của phương pháp 1 để tái sử dụng

Better để thực hiện một chương trình con, nếu chúng ta có nghĩa vụ phải sử dụng chức năng này nhiều lần trong mã của chúng tôi.

sub get_unique { 
    my %seen; 
    grep !$seen{$_}++, @_; 
} 
my @unique = get_unique(@array); 

Phương pháp 3: Sử dụng mô-đun List::MoreUtils

use List::MoreUtils qw(uniq); 
my @unique = uniq(@array); 
Các vấn đề liên quan