2011-08-18 10 views
3

저는 여전히 Perl을 배우므로 아마도이 작업을보다 효율적으로 수행 할 수 있습니다. 나는 해쉬를 가져 오려고 노력하고 있는데, $ values ​​=> $ keys를 되돌리고 새로운 키 (이전 값)를 가져온 다음 그 키를 정렬한다.해시 반전, 키 가져 오기 및 정렬

여기에 문제의 코드입니다 :

foreach my $key (sort keys reverse %hash){ 

...} 

는 내가 일이 기대하고있어 그 역 % 해시 키가 찾고있는 것입니다 해시 유형을 반환합니다. 그러나, 나는 다음과 같은 오류가 발생합니다 : 키에 인수 1의

유형 (반전되지 않음)

나는 역 % 해시 괄호를 넣어 시도했습니다 해시를 수 있지만 여전히 같은 일을 받아야합니다.

이것이 작동하지 않는 이유는 무엇입니까?

답변

6

Perl 함수는 스칼라 값 또는 목록을 반환 할 수 있습니다. 명시 적 해시 반환 유형이 없습니다. (서브 루틴에서 return %hash을 호출 할 수 있지만 Perl은 해시에서 키 - 값 쌍을 암시 적으로 언 롤링하여 목록으로 반환합니다).

따라서 reverse %hash의 반환 값은 해시가 아닌 목록이며 keys의 인수로 사용하기에 적합하지 않습니다. 또한 일종의 values %hash를 사용

foreach my $key (sort values %hash) { ... 

말하여 해시의 값이 keys %{{reverse %hash}}를 사용에서 미묘하게 다른 수

foreach my $key (sort keys %{{reverse %hash}}) { ... 

: 당신은 %{{}} 캐스트와 해시로이 목록을 해석하는 펄을 강제 할 수 keys %{{reverse %hash}}은 중복 값을 반환하지 않습니다.

+0

+1 비 중복 통찰력. – TLP

+0

답장을 보내 주셔서 감사합니다. 이것은 아마도 나의 수준을 넘어서는 길일 것입니다. (나는 Perl 6th Ed을 배우면서 계속 노력하고 있습니다.)하지만 % {{}} 사용에 관해서는 어디서 더 읽을 수 있습니까? 슬프게도 구글은 그 용어에 대해 아무것도 가지고 있지 않다. – dmux

+0

http://perldoc.perl.org/perlref.html 하단의 "참고 자료"섹션에는 몇 가지 링크가 더 있습니다. – TLP

3

난 당신이 정확하게 상황 in this example을 설명하는 것 같아요 :

#!/usr/local/bin/perl 

use strict; 
use warnings; 

my %hash = (one => 1, two => 2, three => 3, four => 4); 

%hash = reverse %hash; 

foreach my $key (sort {$a <=> $b} keys %hash) { 
    print "$key=>$hash{$key}, "; 
} 
print "\n"; 

# it displays: 1=>one, 2=>two, 3=>three, 4=>four 
+0

감사합니다. 이 작업을하는 동안 게시 된 코드가 예상대로 작동하지 않는 이유를 알았습니다. 다시 고마워! – dmux

+0

@chris, 오류 메시지와 마찬가지로 해시를'keys'에 전달하지 않았습니다. – ikegami

4

keys의 인수는 해시, 배열 또는 표현식이 아닌 목록이어야합니다. 그랬다면

keys { reverse %hash } 

브래킷이 익명의 해시를 만들기 때문에 예상 한 결과를 얻을 수 있습니다. 한편, 팸은 우선 순위 만 바꿉니다. 또는이 경우 대부분의 펄 함수는 선택적 괄호를 가지고 있기 때문에이 함수는 아마도 keys() 함수와 관련이있는 것으로 간주됩니다. 당신은 단지 해시 값을 원하는 경우 또한

는, 당신은 사용할 수 있습니다
values %hash 

reverse, values 및 추가 정보를 keys의 설명서를 참조하십시오.

+0

답장을 보내 주셔서 감사합니다. 게시하기 전에 해시에서 역방향 사용을 완전히 이해하지 못했습니다. reverse에 대한 perldoc 페이지에서 역순으로 보이는 것처럼 원래의 해시를 풀고 새 해시를 만듭니다. 그러나, 나는 여전히이 새로운 해쉬가 리버스의 반환 값이라고 생각할 것이다. 반대쪽에 대괄호를 추가하고 % 해시를 시도했지만 여전히 동일한 문제가있었습니다. – dmux

+0

아직도 문제가 있다고 말하는지 모르겠다. 'reverse'는 해시가 아닌 * list *를 반환합니다. 목록은 기본적으로'(1,2,3,4,5,6)'이며,'keys'와 함께 사용하려고한다면, 첫 번째 값은'1'이 될 것이고, 그것을 사용하려고 시도 할 것입니다. 휴식. – TLP

+0

'{reverse % hash}'는 해시에 대한 참조입니다.이 값은'keys'에도 적합하지 않습니다 (Perl> = v5.14 인 해시 참조를 사용할 수 있습니다) – mob

3

Pre 5.14, keys은 해시 키를 반환합니다. 해시가 필요합니다. 당신은 하나도 제공하지 않았습니다. reverse은 해시를 반환하지 않습니다. 사실 스칼라 만 반환 할 수 있으므로 해시를 반환하는 것은 불가능합니다. (내부적으로 Perl은 스택에 직접 해시를 넣을 수 있지만 "기괴한"오류 메시지가 발생하지 않으면 사용자에게 보이지 않습니다.)이 오류는 컴파일 타임에 감지됩니다.

5.14는보다 유연합니다. 또한 해시에 대한 참조를 허용합니다. (배열과 배열에 대한 참조도 받아 들일 것이지만 여기에는 관련이 없습니다.) 참조는 스칼라이므로 함수로 반환 할 수 있습니다. 코드가 실제로 런타임에 실행되지만, reverse이 스칼라 컨텍스트에서 반환하는 것은 존재하지 않는 해시에 대한 참조가 아니므로 코드가 그 시점에서 종료됩니다.


해시를 취소해야 할 이유가 있습니까? 당신이 경우에

foreach my $key (sort { $hash{$a} cmp $hash{$b} } keys %hash) { 
    my $val = $hash{$key}; 
    ... 
} 

, 답장을 보내

foreach my $val (sort keys %{ { reverse %hash } }) { 
    # No access to original key 
    ... 
} 

또는

my %flipped = reverse %hash; 
foreach my $val (sort keys %flipped) { 
    my $key = $flipped{$val}; 
    ... 
}