2011-04-05 4 views
4

해시 배열이 있습니다. 다른 키의 고유성을 기반으로 해시 키의 값 목록을 원합니다.지도 연산에서 반환 된 해시를 + 참조 해제하는 것을 피할 수 있습니까?

my @obs = ({ 
    value => 'three', 
    id => 3 
},{ 
    value => 'one-2', 
    id => 1 
},{ 
    value => 'one', 
    id => 1 
}); 
# This works, prints "one\nthree" 
say for values %{{ map { $_->{id} => $_->{value} } @obs }}; 

은 내가 map 주위 참조 + 역 참조 비트를 피할 수 있습니까? 처음에는 그냥 직접 map의 반환에 values를 호출 시도하지만 펄이 그것을 필요가 없습니다 : 인수 1의

유형 값으로 스크립트 \의 workbench.pl 라인 55 (반복자를지도하지 않음) 해시를해야합니다, "@obs;"근처

답변

7

문제는 values은 실제로 해시가 작동하기를 원합니다. 특별한 이유는 each에 의해 사용 된 장소 소유자를 지우는 것입니다. 실제로 그것을 지우려면 실제 물건이 필요합니다.

두 가지 방법 중 하나를 선택할 수 있습니다. 당신이 심판/DEREF을 좋아하지 않는 경우 첫째, 당신은 단지 한 줄 중 임시 해시의 생성을 당길 수있다 (실제 코드를 %h보다 더 좋은 이름을 선택하십시오) :

my %h = map { $_->{id} => $_->{value} } @obs; 
say for values %h; 

당신이 주변에 걸어 %h을 원하지 않는 경우에, 다만 임시 블록으로 드롭 :

...code code code... 
{ 
    my %h = map { $_->{id} => $_->{value} } @obs; 
    say for values %h; 
} 
...code code code... 

또 다른 방법을 임시 해시 생성 및 values가 무엇을하고 있는지 에뮬레이션 할 수 :

my %seen; 
for (reverse @obs) { say $_->{value} unless $seen{$_->{id}}++ } 

정말 중요한 것은이 데이터로 무엇을 할 것인지입니다. 거꾸로 된 해시 값을 한 번만 입력하면 한 줄짜리 코드가 가장 좋은 해결책이 될 수 있습니다. 나중에이 데이터 (id & 값)가 필요하다면 실제 해시를 생성하고 사용하십시오.이 변환을 한 번 이상 수행하지 마십시오. 단 한 줄로 유지할 수 있습니다.

더 이상의 내용이 없으면 취할 접근법에 대한 조언을하기가 어렵습니다.

+1

데이비드 골든은 'values', 'each','keys' 등의 참조 작업에 대한 작업을하고 있다고 생각합니다. 그것은 5.13 (dev 릴리스)에 있고 5.14 (프로덕션 릴리스)에 있어야합니다. – mpeters

+0

@mpeters, 연산자 과부하로 인한 모호함으로 인해 논쟁의 여지가 있으므로 5.14에서 일부 기능을 실험으로 표시 할 수 있습니다. – ikegami

0

values이 목록에서 작동하는 경우 해당 목록의 모든 두 번째 요소가 필요합니다. 그래서

say for values %{{ map { $_->{id} => $_->{value} } @obs }}; 

지금

say for every_odd map { $_->{id} => $_->{value} } @obs; 

것, 그것은 같은 함수를 작성 전적으로 가능하지만, 그것은 단순히이 경우에 필요하지 않은 것. 하나는 단순히

say for map { $_->{value} } @obs; 

을 수행 할 수 있습니다 그리고 그

say $_->{value} for @obs; 

한 캐치로 단순화 해시를 사용하지 않음으로써, 당신은 중복을 제거하지 않습니다.