Это правильный способ создания хэша Perl, который использует массивы? - PullRequest
5 голосов
/ 24 марта 2010

Я впервые манипулирую хешами и массивами таким образом - и это работает.В принципе, для каждого ключа есть несколько значений, которые я хочу записать, а затем распечатать в виде «ключ -> значение -> значение -> val ...»

Мой код выглядит следующим образом,Я удивлен, что это работает, настолько обеспокоен, что это работает "по ошибке".Это правильный способ выполнения этой задачи, или есть более эффективный или подходящий метод?

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

Ответы [ 3 ]

2 голосов
/ 24 марта 2010

Код выше имеет много ненужных шагов. 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";
}
2 голосов
/ 24 марта 2010

Следующий код делает то же самое, что и ваш код, без лишних шагов.

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 для инициализации записи.

1 голос
/ 24 марта 2010

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

my %result;

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

и не более. Ваши попытки инициализировать хэш не делают то, что вы думаете (и не нужны), ваш цикл while, как написано, вообще не является хорошей идеей, и не все глобальные переменные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...