2010-11-18 35 views
7

Tôi muốn áp dụng một chức năng cho mọi mục trong danh sách và lưu trữ các kết quả tương tự như map(function, list) trong python.Làm cách nào để áp dụng một hàm vào danh sách bằng bản đồ?

Cố gắng để vượt qua một chức năng để lập bản đồ, nhưng đã nhận lỗi này:

perl -le 'my $s = sub {}; @r = map $s 0..9' 
panic: ck_grep at -e line 1. 

cách thích hợp để làm điều này là gì?

Trả lời

7

Nếu một biến vô hướng nắm giữ một tài liệu tham khảo mã - ví dụ:

my $double = sub { 2 * shift }; 

Bạn có thể gọi mã rất nhiều cách mà bạn sẽ bằng Python, như thế này:

$double->(50); # Returns 100. 

Áp dụng đến một map Ví dụ:

my @doubles = map $double->($_), 1..10; 

Hoặc theo cách này:

my @doubles = map { $double->($_) } 1..10; 

Các biến thể thứ hai là mạnh mẽ hơn vì khối được định nghĩa bởi {} niềng răng có thể chứa bất kỳ số lượng báo cáo Perl:

my @doubles = map { 
    my $result = 2 * $_; 

    # Other computations, if needed. 

    $result; # The return of each call to the map block. 
} 1..10; 
+1

Nice câu trả lời, cũng lưu ý rằng trong khối bản đồ, không giống như hầu hết các khối khác, bạn có thể _not_ cài đặt pragmas từ vựng hay làm những hành động thời gian biên dịch khác ('sử dụng ... '/' no ... '). –

+0

Bạn có thể sử dụng * sử dụng * và * không * trong * bản đồ DANH SÁCH BLOCK * dạng * bản đồ *, không có trong * bản đồ EXPR DANH * biểu mẫu, nó chỉ là nếu bạn sử dụng chúng, bạn có thể cần phải phân biệt khối từ một biểu thức với hàng đầu; Ngoài ra, bạn có thể sử dụng * làm BLOCK * làm biểu thức và có thể chứa * no * và * use *. Sử dụng nghiêm ngặt; @a = 1..10; my @b = map {; không có 'vars' nghiêm ngặt; $ x = $ _ + 1; $ x} @a; my @c = map {do {no strict 'vars'; $ x = $ _ + 1; $ x}} @a; – MkV

+0

Cũng đáng chú ý là * $ _ * trong vòng lặp là một bí danh cho các phần tử mảng, do đó, sửa đổi nó sửa đổi mảng nguồn, mà không được khuyến khích cho mã rõ ràng. – MkV

5

thử: map { $s->($_) } (0..9) thay vì map $s 0..9

giải thích: trong bạn Ví dụ, $s là một tham chiếu đến một chương trình con, vì vậy bạn phải dereference nó để cho phép gọi điện thoại subroutin. Điều này có thể đạt được bằng nhiều cách: $s->() hoặc &$s() (và có lẽ một số cách khác mà tôi quên)

4
my $squared = sub { 
     my $arg = shift(); 
     return $arg ** 2; 
    }; 

sau đó, hoặc

my @list = map { &$squared($_) } 0 .. 12; 

hoặc

my @list = map { $squared->($_) } 0 .. 12; 

hoặc có thể

my $squared; 
BEGIN { 
    *Squared = $squared = sub(_) { 
     my $arg = shift(); 
     return $arg ** 2; 
    }; 
} 
my @list = map { Squared } 0 .. 12; 
2

Nó không quá khác biệt so với Python.

@results = map { function($_) } @list; 
@results = map function($_), @list; 

hoặc với "lambdas",

@results = map { $function->($_) } @list; 
@results = map $function->($_), @list; 
Các vấn đề liên quan