为什么 Perl 的each() 不第二次遍历整个散列?
我有一个简单的脚本试图了解 Perl 中的哈希值。
#!/usr/bin/perl
my %set = (
-a => 'aaa',
-b => 'bbb',
-c => 'ccc',
-d => 'ddd',
-e => 'eee',
-f => 'fff',
-g => 'ggg'
);
print "Iterate up to ggg...\n";
while ( my ($key, $val) = each %set ) {
print "$key -> $val \n";
last if ($val eq 'ggg');
}
print "\n";
print "Iterate All...\n";
while ( my ($key, $val) = each %set ) {
print "$key -> $val \n";
}
print "\n";
我对输出感到惊讶:-
Iterate upto ggg...
-a -> aaa
-c -> ccc
-g -> ggg
Iterate All...
-f -> fff
-e -> eee
-d -> ddd
-b -> bbb
我知道键是经过哈希处理的,因此第一个输出可以是“n”个元素,具体取决于内部顺序。 但为什么我之后不能循环数组呢? 怎么了 ?
谢谢,
I have a simple script trying to learn about hashes in Perl.
#!/usr/bin/perl
my %set = (
-a => 'aaa',
-b => 'bbb',
-c => 'ccc',
-d => 'ddd',
-e => 'eee',
-f => 'fff',
-g => 'ggg'
);
print "Iterate up to ggg...\n";
while ( my ($key, $val) = each %set ) {
print "$key -> $val \n";
last if ($val eq 'ggg');
}
print "\n";
print "Iterate All...\n";
while ( my ($key, $val) = each %set ) {
print "$key -> $val \n";
}
print "\n";
I am surprised by the output:-
Iterate upto ggg...
-a -> aaa
-c -> ccc
-g -> ggg
Iterate All...
-f -> fff
-e -> eee
-d -> ddd
-b -> bbb
I understand that the keys are hashed so the first output can be 'n' elements depending on the internal ordering. But why am I not able to just loop the array afterward? What's wrong ?
Thanks,
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
each
使用与哈希关联的指针来跟踪迭代。 它不知道第一个 while 循环与第二个 while 循环不同,并且它在它们之间保留相同的指针。大多数人出于这个(和其他)原因避免使用
each
,而是选择keys
:这也使您可以控制迭代顺序:
无论如何,如果您想提前结束循环,请避免
each
。顺便说一句,函数式编程的倡导者应该借此机会指出隐藏状态的缺点。 看起来像无状态的操作(“循环表中的每一对”)实际上是有状态的。
each
uses a pointer associated with the hash to keep track of iteration. It does not know that the first while is different from the second while loop, and it keeps the same pointer between them.Most people avoid
each
for this (and other) reasons, instead opting forkeys
:This gives you control over the iteration order, as well:
Anyway, if you are going to end the loop early, avoid
each
.BTW, functional programming advocates should take this opportunity to point out the disadvantages of hidden state. What looks like a stateless operation ("loop over each pair in a table") is actually quite stateful.
您可以在每个 上读取 perldoc
当完全读取散列时,会在列表上下文中返回一个空数组(分配时会产生 false (0)
值),以及标量上下文中的“undef”。 之后对“each”的下一次调用将再次开始迭代。 有一种罪孽——
每个哈希的 gle 迭代器,由程序中的所有“each”、“keys”和“values”函数调用共享; 它可以通过重置
从哈希中读取所有元素,或者通过评估“keys HASH”或“values HASH”。
因此,您可以在代码中使用keys %set 再次迭代(由于您的“last”语句)
you can read the perldoc on each
When the hash is entirely read, a null array is returned in list context (which when assigned produces a false (0)
value), and "undef" in scalar context. The next call to "each" after that will start iterating again. There is a sin‐
gle iterator for each hash, shared by all "each", "keys", and "values" function calls in the program; it can be reset by
reading all the elements from the hash, or by evaluating "keys HASH" or "values HASH".
therefore, you can use keys %set in your code to iterate again (due to you "last" statement)