Perl 해시의 키를 반복하는 가장 안전한 방법은 무엇입니까?


Answers

each 을 사용할 때주의해야 할 한 가지는 해시에 "상태"를 추가하는 부작용이 있다는 것입니다 (해시는 "다음"키가 무엇인지 기억해야합니다). 위에 게시 된 스 니펫과 같은 코드를 사용하면 한 번에 전체 해시를 반복하므로 일반적으로 문제가되지 않습니다. 그러나 each 키를 처리하기 전에 while ... each 루프를 사용하여 last 또는 return while ... each 과 같은 명령문을 사용하여 while ... each 루프를 종료 할 때 문제를 추적 할 수 있습니다 (경험적으로 말하면).

이 경우 해시는 이미 반환 된 키를 기억하고 다음 번에 each 을 사용할 때 (아마도 관련이없는 전체 코드에서)이 위치에서 계속됩니다.

예:

my %hash = ( foo => 1, bar => 2, baz => 3, quux => 4 );

# find key 'baz'
while ( my ($k, $v) = each %hash ) {
    print "found key $k\n";
    last if $k eq 'baz'; # found it!
}

# later ...

print "the hash contains:\n";

# iterate over all keys:
while ( my ($k, $v) = each %hash ) {
    print "$k => $v\n";
}

인쇄 내용 :

found key bar
found key baz
the hash contains:
quux => 4
foo => 1

"bar"와 "baz"키는 어떻게 되었습니까? 여전히 존재하지만 두 번째 키는 첫 번째 키가 중단 된 곳에서 시작하여 해시 끝 부분에 도달하면 멈 춥니 다. 따라서 두 번째 루프에서 키를 볼 수 없습니다.

Question

내가 (키, 값) 쌍을 가진 Perl 해시를 가지고 있다면, 모든 키를 반복하는 기본 방법은 무엇입니까? each 방법을 사용하면 의도하지 않은 부작용이 생길 수 있다고 들었습니다. 그래서, 그게 사실이고, 다음 두 가지 방법 중 가장 좋은 방법인가, 아니면 더 좋은 방법이 있습니까?

# Method 1
while (my ($key, $value) = each(%hash)) {
    # Something
}

# Method 2
foreach my $key (keys(%hash)) {
    # Something
}



나는 보통 keys 사용하고, 내가 마지막으로 사용하거나 each 의 사용법을 읽을 때를 생각할 수 없다.

루프에서 수행중인 작업에 따라 map 잊지 마세요.

map { print "$_ => $hash{$_}\n" } keys %hash;



나는 항상 방법 2도 사용한다. 각각을 사용하는 것의 유일한 이점은 해시 항목의 값을 읽는 것보다 (다시 할당하는 것이 아니라) 해시 항목을 끊임없이 참조 해제하지 않는다는 것입니다.




각 구문을 사용하면 키 집합 전체가 동시에 생성되지 않습니다. 수백만 개의 행이있는 데이터베이스에 연결된 해시를 사용하는 경우 중요 할 수 있습니다. 한 번에 전체 키 목록을 생성하고 실제 메모리를 소모하지 않으려 고합니다. 루프가 시작되기 전에 키가 실제로 전체 배열을 생성하는 반면이 경우 각각은 반복자 역할을합니다.

그래서, "각"실제 사용의 유일한 장소는 해시가 매우 클 때입니다 (사용 가능한 메모리와 비교). 이는 핸드 헬드 데이터 수집 디바이스 나 메모리가 적은 프로그램을 프로그래밍하지 않는 한 해시 자체가 메모리 자체에 저장되지 않는 경우에만 발생할 가능성이 높습니다.

메모리가 문제가되지 않는다면 일반적으로 맵 또는 키 패러다임이 더 유용하고 읽기 쉬운 패러다임입니다.