2010-03-24 6 views
5

이 방법으로 해시와 배열을 조작 한 것은 이번이 처음입니다. 기본적으로 모든 키에 대해 여러 값을 기록한 다음 "키 -> 값 -> 값 -> 값 ..."형식으로 인쇄합니다.배열을 사용하는 Perl 해시를 빌드하는 올바른 방법입니까?

내 코드는 다음과 같습니다. 나는 그것이 효과가 있다는 것에 놀랐으며, "실수로"효과가 있다고 우려했다. 이 작업을 수행하는 올바른 방법입니까 아니면 더 효율적이거나 적절한 방법이 있습니까?

while ($source =~ m/(regex)/g) { #Get all key names from source 
    $listkey = $1; #Set current list key to the current regex result. 
    $list{$listkey} = ++$i unless $list{$listkey}; #Add the key to the hash unless it already exists. 
    $list{$listkey} = [] unless exists $list{$listkey}; #Add an array for the hash unless the hash already exists. 
    while ($loopcount==0) { 
      if ($ifcount==0) { 
        $listvalue=result_of_some_function_using_list_key; #Get the first list value by using the list key. 
        $ifcount++; #Increment so we only get the first list value once. 
      } else { 
        $listvalue=result_of_some_function_using_list_value; #Update the list value by using the last list value. 
      } 
      if ($listvalue) { #If the function returned a value... 
        push @{$list{$listkey}}, $listvalue; #...then add the value to the hash array for the key. 
      } else { #There are no more values and we need a new key. 
        $listkey=0; #Reset variable. 
        $listvalue=0; #Reset variable. 
        $loopcount++; #Increment loop counter to exit loop. 
      } 
    } 
$ifcount=0; #Reset count variable so the next listvalue can be generated from the new key. 
    $loopcount=0; #Reset count variable so another loop can begin for a new key. 
} 
foreach $listkey (keys %list) { #For each key in the hash. 
    print "$listkey --> "; #Print the key. 
    @values = @{$list{$listkey}}; #Reference the arrays of the hash. 
    print join ' --> ', @values; #Print the values. 
    print "\n"; #Print new line. 
} 
+7

정말로 'use strict; 경고 사용; mode – Zaid

+0

악의적 인 경고 목록이 생성되었습니다. 나는 그들을 통과해야 할 것이다. – Structure

+4

실제 코드에는이 주석이 많지 않기를 바라고 있습니다. –

답변

2

다음 코드는 불필요한 단계를 거치지 않고, 코드와 동일한 작업을 수행합니다.

while ($source =~ m/(regex)/g) { # Get all key names from source 
    $listkey = $1;   # Grab current regex result. 
    $listvalue = result_of_some_function_using_list_key; 
    while ($listvalue) { 
     push @{$list{$listkey}}, $listvalue; 
     $listvalue = result_of_some_function_using_list_value; 
    } 
    $listkey = 0;    # Reset variable. 
    $domain = 0;     # Reset variable. 
} 

그러나 다른 사람들이 언급 한 것처럼 대부분의 경우 전역 변수는 피해야합니다. 대신 목록 키와 목록 값은 어휘로 범위가 my()이어야하며 목록 값을 생성하는 함수는 입력으로 하나 이상의 매개 변수 (도메인, 목록 키 및/또는 목록 값)를 가져야합니다. 원래 코드에서

의 선

$list{$listkey} = ++$i unless $list{$listkey}; 
$list{$listkey} = [] unless exists $list{$listkey}; 

는이 항목을 초기화 push @{ $list{$key} }, $value에 충분하다, 필요하지 않습니다.

+0

감사합니다. 간략한 설명을 한 후에 잘못된 부분을 잘 이해했습니다. – Structure

1

아니요! 이 방법이 성공한다면, 그것은 분명히 "실수로"입니다. 그러나 이것이 실제 코드가 아니며 예제에 "번역"하는 데 몇 가지 실수를 추가 했으므로 의도가 정확히 무엇인지 판단하기는 어렵지만 프로그램의 골격에서 보면 모양이 분명합니다. 그것은 다음과 같이되어야합니다 :

my %result; 

while ($source =~ m/(regex)/g) { 
    my $key = $1; 
    my $value = mangle($key); 
    while ($value) { 
    push @{ $results{$key} }, $value; 
    $value = frob($value); 
    } 
} 

그리고 더 이상 없습니다. 해시를 초기화하려는 시도는 자신이 생각하는대로하지 않으며 필요하지도 않습니다. 작성한 while 루프는 전혀 좋은 아이디어가 아니며 모든 글로벌 변수가 아닙니다.

2

위의 코드는 많은 불필요한 단계가 있습니다. 펄은 매우 표현 언어이며,이 같은 논리는 아주 간단하게 표현 될 수 있습니다 :

# uncomment for some sample data 
# sub function {"@_" !~ /^\[{3}/ and "[@_]"} 
# my $source = 'one two three'; 

my %list; 
while ($source =~ m/(\S+)/g) { 
    my $key = $1; 
    my $value = function($key); 

    while ($value) { 
     push @{ $list{$key} }, $value; 
     $value = function($value) 
    } 
} 

for my $key (keys %list) { 
    print join(' --> ' => $key, @{$list{$key}}), "\n"; 
} 
+0

이 동의했습니다. 일반적으로 Perl에서는 루프 인덱스 (실제로 for ($ i = 0 ... C 스타일 루프) 또는 카운터를 볼 수 있어야합니다. 실제로 카운터와 인덱스는 카운터 값과 함께 수행해야하는 경우가 많습니다. awkward-to-spot 버그의 좋은 원천 – plusplus

관련 문제