Действительно ли это - корректный способ создать хеш Perl, который использует массивы?

Это - первый раз, когда я управлял хешами и массивами таким образом - и он работает. В основном для каждого ключа существует несколько значений, которые я хочу записать и затем распечатать в форме "ключ-> значение-> значение-> 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.
}
5
задан Structure 24 March 2010 в 07:03
поделиться

3 ответа

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

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

2
ответ дан 14 December 2019 в 19:08
поделиться

В приведенном выше коде много ненужных шагов. 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
ответ дан 14 December 2019 в 19:08
поделиться

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

my %result;

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

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

1
ответ дан 14 December 2019 в 19:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: