2010-07-15 29 views
5

Tôi cần phải đi qua một mảng, và điều kiện xóa các yếu tố, trong Perl. Tôi biết về slice, nhưng tôi không biết cách sử dụng nó trong ngữ cảnh foreach.Perl tương đương với 'từ chối' của Ruby?

Trong Ruby, có reject!:

foo = [2, 3, 6, 7] 
foo.reject! { |x| x > 3 } 
p foo # outputs "[2, 3]" 

Có tương đương Perl?

Trả lời

22
@foo = (2, 3, 6, 7); 
@foo = grep { $_ <= 3 } @foo; 
print @foo; # 23 
+0

Woah, ấn tượng. Tôi nghĩ rằng tôi đã hỏi một câu hỏi Perl của người mới bắt đầu hoàn chỉnh ở đó, nhưng câu trả lời của bạn là câu trả lời thứ ba của bạn. : o –

+0

@ Shtééf: câu hỏi của người mới bắt đầu thường là những câu hỏi hữu ích. –

+0

@knittl giải pháp của bạn có thể được mở rộng để thay thế <= bằng cụm từ thông dụng không? – Bnjmn

8

Như câu trả lời khác đề nghị, grep thường là tất cả các bạn cần.

Tuy nhiên, nó có thể với perl prototypes mã một hàm rằng, giống như ruby ​​của Array#reject!:

  • chấp nhận một khối
  • có thể sửa đổi mảng đối số của nó ở vị trí

Cách sử dụng là:

@foo = (2, 3, 6, 7);   # Void context - modify @foo in place 
reject { $_ > 3 } @foo;   # @foo is now (2, 3) 

@foo = (2, 3, 6, 7);   # Scalar context - modify @foo in place 
$n = reject { $_ > 3 } @foo; # @foo is now (2, 3), $n is length of modified @foo 

@foo = (2, 3, 6, 7);   # Array context - return a modified copy of @foo 
@cpy = reject { $_ > 3 } @foo; # @cpy is (2, 3), @foo is (2, 3, 6, 7) 

Thực hiện:

sub reject(&\@) { 
    my ($block, $ary) = @_; 

    # Return a copy in an array context 
    return grep {! $block->() } @$ary if wantarray; 

    # Otherwise modify in place. Similar to, but not 
    # quite, how rb_ary_reject_bang() does it. 
    my $i = 0; 
    for (@$ary) { 
      next if $block->(); 
      ($ary->[$i], $_) = ($_, $ary->[$i]); # swap idiom to avoid copying 
      $i++;        # possibly huge scalar 
    } 
    $#$ary = $i - 1; # Shorten the input array 

    # We differ from Array#reject! in that we return the number of 
    # elements in the modified array, rather than an undef value if 
    # no rejections were made 
    return scalar(@$ary) if defined(wantarray); 
} 
+0

+1 Ngọc trai Perl. – Konerak

+0

Cảm ơn, @Konerak. Giống như nhiều người khác, tôi có xu hướng né tránh nguyên mẫu/khối cú pháp, nhưng điều này có vẻ trực quan và có thể hữu ích. :) – pilcrow

+0

Danh sách của CPAN :: UtilsBy có hàm extract_by() giống như từ chối ở trên, nhưng nó trả về các phần tử bị từ chối (ở đây được gọi là phần tử trích xuất) thay vì bản sao của mảng mà bạn đã có (và bạn rõ ràng muốn làm việc với anyway, khác tại sao bận tâm sửa đổi nó). Tôi nghĩ rằng hàm của Leonerd là một giá trị trả về hữu ích hơn. Nó cũng sử dụng \ @ proto. – masonk

Các vấn đề liên quan