Это - первый раз, когда я управлял хешами и массивами таким образом - и он работает. В основном для каждого ключа существует несколько значений, которые я хочу записать и затем распечатать в форме "ключ-> значение-> значение-> 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.
}
Следующий код делает то же самое, что и ваш код, без лишних шагов.
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
для инициализации записи.
В приведенном выше коде много ненужных шагов. 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";
}
Нет! Если это сработает, то однозначно «по ошибке». Но также очевидно, что это не ваш реальный код и что вы добавили еще несколько ошибок при «переводе» его в пример, поэтому трудно точно судить, в чем заключалась цель, но, исходя из скелета вашей программы, это выглядит вроде должно быть что-то вроде:
my %result;
while ($source =~ m/(regex)/g) {
my $key = $1;
my $value = mangle($key);
while ($value) {
push @{ $results{$key} }, $value;
$value = frob($value);
}
}
и не более. Ваши попытки инициализировать хеш не делают того, что вы думаете (и не являются необходимыми), ваш цикл while в том виде, в котором он написан, вообще не является хорошей идеей, как и все глобальные переменные.