Perl : if (목록의 요소)
목록에 요소가 있는지 찾고 있습니다.
Python에는 in
키워드 가 있으며 다음과 같은 작업을 수행합니다.
if element in list:
doTask
전체 목록을 수동으로 반복하지 않고도 Perl에 동등한 것이 있습니까?
최신 정보:
v5.10.0에서 추가되고 v5.10.1에서 대폭 수정 된 스마트 매치는 일반적인 불만 사항이었습니다. 유용한 방법은 여러 가지가 있지만 Perl의 사용자와 구현 자 모두에게 문제가되고 혼란 스럽습니다. 문제를 가장 잘 해결하는 방법에 대한 많은 제안이있었습니다. 스마트 매치는 거의 확실히 미래에 변경되거나 사라질 것임이 분명합니다. 현재 동작에 의존하지 않는 것이 좋습니다.
이제 파서가 ~~, 주어진 또는 언제를 볼 때 경고가 발행됩니다.
Perl v5.10이 필요하지 않은 경우 다음 예제 중 하나를 사용할 수 있습니다.
스마트 일치
~~
연산자.if( $element ~~ @list ){ ... } if( $element ~~ [ 1, 2, 3 ] ){ ... }
given
/when
구문을 사용할 수도 있습니다 . 내부적으로 스마트 매치 기능을 사용합니다.given( $element ){ when( @list ){ ... } }
for
루프를 "토픽 라이저"로 사용할 수도 있습니다 (설정 됨$_
).for( @elements ){ when( @list ){ ... } }
Perl 5.12에서 나올 한 가지는 when
. 더 좋아 if
하고 unless
.
given( $element ){
... when @list;
}
이전 버전의 Perl에서 실행할 수 있어야하는 경우 몇 가지 옵션이 있습니다.
List :: Util :: first 를 사용하면 벗어날 수 있다고 생각할 수 있지만 문제를 일으키는 몇 가지 가장자리 조건이 있습니다.
이 예에서 우리가
0
. 불행히도이 코드는failure
매번 인쇄 됩니다.use List::Util qw'first'; my $element = 0; if( first { $element eq $_ } 0..9 ){ print "success\n"; } else { print "failure\n"; }
의 반환 값이
first
정의 되었는지 확인할 수 있지만 실제로 일치undef
가 성공하기를 원하면 실패합니다 .grep
그러나 안전하게 사용할 수 있습니다 .if( grep { $element eq $_ } 0..9 ){ ... }
grep
스칼라 컨텍스트에서 호출 되므로 안전 합니다. 배열은 스칼라 컨텍스트에서 호출 될 때 요소 수를 반환합니다. 그래서 이것은 우리가에 매치를 시도하더라도 계속 작동 할 것undef
입니다.둘러싸는
for
루프를 사용할 수 있습니다 .last
성공적인 경기에서 루프를 종료 하려면을 호출하십시오 . 그렇지 않으면 코드를 두 번 이상 실행하게 될 수 있습니다.for( @array ){ if( $element eq $_ ){ ... last; } }
문
for
조건에 루프를 넣을 수 있습니다if
...if( do{ my $match = 0; for( @list ){ if( $element eq $_ ){ $match = 1; last; } } $match; # the return value of the do block } ){ ... }
... 문
for
앞에 루프 를 두는 것이 더 명확 할 수 있습니다if
.my $match = 0; for( @list ){ if( $_ eq $element ){ $match = 1; last; } } if( $match ){ ... }
문자열에 대해서만 일치하는 경우 해시를 사용할 수도 있습니다. 이 경우 프로그램의 속도를 높일 수 있습니다
@list
큰 하고 당신에 대해 일치에 가고,%hash
여러 번. 특히@array
변경되지 않으면%hash
한 번만 로드 하면됩니다.my %hash = map { $_, 1 } @array; if( $hash{ $element } ){ ... }
자신 만의 서브 루틴을 만들 수도 있습니다. 이것은 프로토 타입 을 사용하는 것이 유용한 경우 중 하나입니다 .
sub in(&@){ local $_; my $code = shift; for( @_ ){ # sets $_ if( $code->() ){ return 1; } } return 0; } if( in { $element eq $_ } @list ){ ... }
if( $element ~~ @list ){
do_task
}
~~
는 "스마트 매치 연산자"이며, 단순히 멤버십 감지를 나열하는 것 이상을 수행합니다.
$foo = first { ($_ && $_ eq "value" } @list; # first defined value in @list
또는 수동 롤링 유형의 경우 :
my $is_in_list = 0;
foreach my $elem (@list) {
if ($elem && $elem eq $value_to_find) {
$is_in_list = 1;
last;
}
}
if ($is_in_list) {
...
매우 긴 목록에서는 약간 다른 버전이 다소 빠를 수 있습니다.
my $is_in_list = 0;
for (my $i = 0; i < scalar(@list); ++$i) {
if ($list[i] && $list[i] eq $value_to_find) {
$is_in_list = 1;
last;
}
}
if ($is_in_list) {
...
이 작업을 여러 번 수행하려는 경우 조회 시간에 대한 공간을 절충 할 수 있습니다.
#!/usr/bin/perl
use strict; use warnings;
my @array = qw( one ten twenty one );
my %lookup = map { $_ => undef } @array;
for my $element ( qw( one two three ) ) {
if ( exists $lookup{ $element }) {
print "$element\n";
}
}
요소가 나타나는 횟수 @array
가 중요하지 않고의 내용 @array
이 단순 스칼라 라고 가정합니다 .
목록 :: MoreUtils
perl> = 5.10에서는 다른 많은 사람들이 이미 말했듯이 스마트 매치 연산자가 확실히 가장 쉬운 방법입니다.
이전 버전의 perl에서는 대신 List :: MoreUtils :: any 를 제안 합니다 .
List::MoreUtils
핵심 모듈은 아니지만 (일부는 그래야한다고 말함) 매우 인기가 있으며 주요 펄 배포판에 포함되어 있습니다.
다음과 같은 장점이 있습니다.
- (파이썬 에서처럼) 참 / 거짓을 반환
in
하고 요소의 값은 반환List::Util::first
하지 않습니다 (위에서 언급 한 것처럼 테스트하기 어렵게 만듭니다). - 와 달리
grep
테스트를 통과 한 첫 번째 요소에서 중지됩니다 (perl의 스마트 매치 오퍼레이터 단락 도 마찬가지입니다). - 모든 펄 버전에서 작동합니다 (적어도> = 5.00503).
다음을 포함하여 검색된 (스칼라) 값으로 작동하는 예는 다음과 같습니다 undef
.
use List::MoreUtils qw(any);
my $value = 'test'; # or any other scalar
my @array = (1, 2, undef, 'test', 5, 6);
no warnings 'uninitialized';
if ( any { $_ eq $value } @array ) {
print "$value present\n"
}
추신
(프로덕션 코드에서는 범위를 좁히는 것이 좋습니다 no warnings 'uninitialized'
).
TIMTOWTDI
sub is (&@) {
my $test = shift;
$test->() and return 1 for @_;
0
}
sub in (@) {@_}
if( is {$_ eq "a"} in qw(d c b a) ) {
print "Welcome in perl!\n";
}
grep
여기에 도움이된다
if (grep { $_ eq $element } @list) {
....
}
Probably Perl6::Junction
is the clearest way to do. No XS dependencies, no mess and no new perl version required.
use Perl6::Junction qw/ any /;
if (any(@grant) eq 'su') {
...
}
This blog post discusses the best answers to this question.
As a short summary, if you can install CPAN modules then the best solutions are:
if any(@ingredients) eq 'flour';
or
if @ingredients->contains('flour');
However, a more usual idiom is:
if @any { $_ eq 'flour' } @ingredients
which i find less clear.
But please don't use the first() function! It doesn't express the intent of your code at all. Don't use the "Smart match" operator: it is broken. And don't use grep() nor the solution with a hash: they iterate through the whole list. While any() will stop as soon as it finds your value.
Check out the blog post for more details.
PS: i'm answering for people who will have the same question in the future.
Autoload 해킹 을 수행하면 Perl에서 유사한 구문을 수행 할 수 있습니다 .
자동로드를 처리 할 작은 패키지를 만듭니다.
package Autoloader;
use strict;
use warnings;
our $AUTOLOAD;
sub AUTOLOAD {
my $self = shift;
my ($method) = (split(/::/, $AUTOLOAD))[-1];
die "Object does not contain method '$method'" if not ref $self->{$method} eq 'CODE';
goto &{$self->{$method}};
}
1;
그런 다음 다른 패키지 또는 기본 스크립트에는 메서드 호출을 시도 할 때 Autoload에 의해 처리되는 축복받은 객체를 반환하는 서브 루틴이 포함됩니다.
sub element {
my $elem = shift;
my $sub = {
in => sub {
return if not $_[0];
# you could also implement this as any of the other suggested grep/first/any solutions already posted.
my %hash; @hash{@_} = ();
return (exists $hash{$elem}) ? 1 : ();
}
};
bless($sub, 'Autoloader');
}
이것은 다음과 같은 사용법을 남깁니다.
doTask if element('something')->in(@array);
클로저와 그 인수를 재구성하는 경우 구문을 다른 방식으로 전환하여 다음과 같이 보이게 할 수 있습니다. 이는 autobox 스타일에 조금 더 가깝습니다.
doTask if search(@array)->contains('something');
이를 수행하는 기능 :
sub search {
my @arr = @_;
my $sub = {
contains => sub {
my $elem = shift or return;
my %hash; @hash{@arr} = ();
return (exists $hash{$elem}) ? 1 : ();
}
};
bless($sub, 'Autoloader');
}
참고 URL : https://stackoverflow.com/questions/2383505/perl-if-element-in-list
'Development Tip' 카테고리의 다른 글
.NET 소스 코드가 디버깅 중단 점을 하드 코딩 할 수 있습니까? (0) | 2020.11.03 |
---|---|
Java 맵 항목 업데이트 (0) | 2020.11.03 |
파이썬에서 정수를 반올림하는 방법 (0) | 2020.11.03 |
@ Html.DropDownList ()를 사용하여 선택할 CSS 클래스 추가 (0) | 2020.11.03 |
git에서 커밋 한 후 자동으로 푸시하는 방법은 무엇입니까? (0) | 2020.11.03 |