2013-05-10 22 views
1

$描述是从格式YAML输入perl的永恒循环问题

main_key: 
- 
    key1:value2 
    key2:value2 
- 
    key1:value1 
    key2:value2 

的YAML文件输入基本上是散列阵列的散列。

I输入$描述和处理内散列如下:

while ( my ($mod, $defined) = each %{ $description }) { 
    my $index = 0; 
    foreach (@{ $defined }) { 
    while (my ($key, $value) = each %{ $_ }) { 
     process ($key, $mod, $description, $index); 
    } 
    $index = $index + 1; 
    } 
} 

当某些“关键字”作为键I代替添加更多的键,值对于内散列 功能1()和函数2()返回一个哈希指针。

sub process { 
     my ($key, $mod, $description, $index) = @_; 
     my $parameters; 
     if ($key eq 'keyword') { 
      $parameters = function1(); 
     } 
     else { 
      $parameters = function2(); 
     } 
     $description->{$mod}[$index] = { %$parameters, %{$description->{$mod}[$index]} }; 
} 

这里的问题是,“虽然(我($键,$值)=每%{$ _})”在主代码运行永远的,一遍又一遍使用相同的密钥和值。

回答

1

是的。不要这样做。

永远不要在循环时修改散列。从perldoc -f each

如果您添加或删除哈希的元素,同时遍历它, 条目可以跳过或重复的 - 所以不要做。

一般模式是建立修改列表,然后在循环结束后将其修改。当然,您可以将该序列嵌入到迭代散列的外循环中,直到不需要进行更多修改。

+0

是这个答案并不让我感到惊讶。 – evolution 2013-05-10 23:51:32

+0

但是我做了散列的副本,并尝试修改副本。同样的结果。我检查以确保HASH引用指向单独的内存。基本上我通过了$ description_copy(指向不同的mem和原始描述的副本到进程函数 – evolution 2013-05-10 23:52:34

1

此代码的重构工作正常。我已经重写了process以完成最内层哈希所需的所有操作。我已经命名这些$item,因为我不知道它们应该代表什么。请将其修改为更具描述性的内容。

从来就没有任何理由来传递所有这些参数,作为$description$mod的值,并且$index只使用利用$description->{$mod}[$index]因此它可能也已经被直接传递作为参考,以找到相关的散列,其是我所做的。另外,因为process现在循环遍历数组内容,所以不需要传递$key,所以子程序现在只有一个参数。

$item每个元素被检查,并且用于从function1function2适当获得并被推到@params,而不是被插入直远该元素被添加的数据的新的哈希。

一旦所有新值已经建立,它们全部被添加到$item中,并且过程完成。

for my $defined (values %$description) { 
    process($_) for @$defined; 
} 

sub process { 
    my ($item) = @_; 
    my @params; 

    for my $key (keys %$item) { 
    push @params, $key eq 'keyword' ? function1() : function2(); 
    } 

    for my $params (@params) { 
    @{$item}{keys %$params} = values %{$params}; 
    } 
} 
+0

)感谢您查看此内容。我需要一些时间将它集成到我的代码中,并会回复给您。看起来,这里的主要区别在于,该进程正在修改哈希级别,而不是每次将单个键传递给该进程。我们仍在修改我们在循环访问时正在启用的哈希“描述”。 – evolution 2013-05-11 10:06:27

+0

@evolution:是的,'$ description'的*内容*正在被修改。数组散列中的每个散列都通过引用传递给它被修改的“进程”。主要区别在于所需的修改是在'@ params'中累加的,并且在子程序检查完所有的键之后应用*。这与您的代码不同,因为在检查每个密钥时添加了新元素,导致无限循环。 – Borodin 2013-05-11 10:36:03