2010-03-28 3 views
10

해시 배열을 포함하는 해시 인 데이터 구조가 있습니다. 나는 거기에 도달하고 내가 찾는 값과 일치하는 첫 번째 해시를 꺼내고 싶습니다. 나는이 시도 :Perl의 shift가 왜 불평합니까? 'shift 할 arg 타입 1은 array (grep iterator가 아님)이어야합니다.'

my $result = shift grep {$_->{name} eq 'foo'} @{$hash_ref->{list}}; 

을하지만 그 날이 오류를 제공합니다 Type of arg 1 to shift must be array (not grep iterator). 내가 grep에 대한 perldoc을 다시 읽어 봤는데, 내가 무엇을하고있어 말이 생각합니다. grep는 목록을 반환합니다. 틀린 맥락입니까?

지금 임시 변수를 사용 하겠지만 왜 이것이 작동하지 않는지 알고 싶습니다.

답변

18

A list isn't an array.

my ($result) = grep {$_->{name} eq 'foo'} @{$hash_ref->{list}}; 

... 작업을 수행해야합니다. 목록 컨텍스트에서 grep을 반환하지만 첫 번째 값 이외의 값은 지정하지 마십시오.

+5

필자는 화이트리스트에 '목록이 배열이 아니다'라고 100 번 쓰겠다고 생각합니다. 감사. – wes

+0

FAQ에 대한 더 나은 답변이 있습니다. http://www.effectiveperlprogramming.com/blog/39 –

+0

@brian d foy - FAQ는 언제 업데이트됩니까? (즉, Perl 5 버전 10의 포인트 릴리스에서 보시겠습니까? 아니면 버전 12에 있습니까?) – Quentin

17

나는 더 좋은 방법이이 것 쓸 생각 :

use List::Util qw/first/; 

my $result = first { $_->{name} eq 'foo' } @{ $hash_ref->{list} }; 

뿐만 아니라 당신이 당신의 배열을 grepping 중지하기 때문에 더 빨리, 그것도 것을하려고하는지 더 명확 할 것이다 일치하는 요소를 찾으면

2

또 다른 방법은 그것을 할 수 있습니다 : grep에 첫 번째 인수 주위에 중괄호이 경우 중복 것을

my $result = (grep {$_->{name} eq 'foo'} @{$hash_ref->{list}})[0]; 

주, 당신이 블록 설치 및 해체 비용을 피할 수 있도록

my $result = (grep $_->{name} eq 'foo', @{$hash_ref->{list}})[0]; 

“List value constructors” in perldata 목록의 하위 첨자 문서 :

A list value may also be subscripted like a normal array. You must put the list in parentheses to avoid ambiguity. For example:

# Stat returns list value. 
$time = (stat($file))[8]; 

# SYNTAX ERROR HERE. 
$time = stat($file)[8]; # OOPS, FORGOT PARENTHESES 

# Find a hex digit. 
$hexdigit = ('a','b','c','d','e','f')[$digit-10]; 

# A "reverse comma operator". 
return (pop(@foo),pop(@foo))[0]; 

기억하기 바란다. Randal Schwartz이 농담으로 제안했을 때이 기능을 얻었고 그 당시의 패치 적용 기계였던 Chip Salzenberg은 그날 저녁에 구현했다.

업데이트 : 검색의 비트는 제가 염두에 두었던 기능이 $coderef->(@args)임을 보여줍니다. 커밋 메시지는 대화를 기록합니다.

관련 문제