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



3 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
}



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

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

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




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




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

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

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


Related