为什么 Perl 的each() 不第二次遍历整个散列?

发布于 2024-07-27 18:09:11 字数 753 浏览 4 评论 0原文

我有一个简单的脚本试图了解 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

走走停停 2024-08-03 18:09:11

each 使用与哈希关联的指针来跟踪迭代。 它不知道第一个 while 循环与第二个 while 循环不同,并且它在它们之间保留相同的指针。

大多数人出于这个(和其他)原因避免使用 each,而是选择 keys

for my $key (keys %hash){
    say "$key => $hash{$key}";
}

这也使您可以控制迭代顺序:

for my $key (sort keys %hash){
    say "$key => $hash{$key}";
}

无论如何,如果您想提前结束循环,请避免 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 for keys:

for my $key (keys %hash){
    say "$key => $hash{$key}";
}

This gives you control over the iteration order, as well:

for my $key (sort keys %hash){
    say "$key => $hash{$key}";
}

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.

从来不烧饼 2024-08-03 18:09:11

您可以在每个 上读取 perldoc

perldoc -f each

当完全读取散列时,会在列表上下文中返回一个空数组(分配时会产生 false (0)
值),以及标量上下文中的“undef”。 之后对“each”的下一次调用将再次开始迭代。 有一种罪孽——
每个哈希的 gle 迭代器,由程序中的所有“each”、“keys”和“values”函数调用共享; 它可以通过重置
从哈希中读取所有元素,或者通过评估“keys HASH”或“values HASH”。

因此,您可以在代码中使用keys %set 再次迭代(由于您的“last”语句)

print "Iterate upto ggg...\n";
while ( my ($key, $val) = each %set ) {
    print "$key -> $val \n";
    last if ($val eq 'ggg');
}
print "\n";
keys %set;
print "Iterate All...\n";
while ( my ($key, $val) = each %set ) {
    print "$key -> $val \n";
}
print "\n";

you can read the perldoc on each

perldoc -f 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)

print "Iterate upto ggg...\n";
while ( my ($key, $val) = each %set ) {
    print "$key -> $val \n";
    last if ($val eq 'ggg');
}
print "\n";
keys %set;
print "Iterate All...\n";
while ( my ($key, $val) = each %set ) {
    print "$key -> $val \n";
}
print "\n";
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文