2010-03-24 3 views
5

Это первый раз, когда я манипулировал хэшами и массивами таким образом - и он работает. В принципе, для каждого ключа есть несколько значений, которые я хочу записать, а затем распечатать в форме «key-> value -> value -> val ...»Это правильный способ создания хэша 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

Nope! Если это работает, это определенно «по ошибке». Но также очевидно, что это не ваш настоящий код, и вы добавили еще несколько ошибок в «перевод» его на пример, поэтому трудно точно судить о намерении, но, исходя из скелета вашей программы, он выглядит как это должно быть примерно так:

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

В приведенном выше коде много ненужных шагов. Perl является очень выразительным языком, и позволяет логику, как это можно выразить очень просто:

# 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-style) или счетчики в случаях, когда вам действительно нужно что-то делать с этими значениями. Также часто используются счетчики и индексы хороший источник неудобных ошибок – plusplus

Смежные вопросы