如何在perl中从一个非常大的散列中获取一个键(随机ok)?

如何在perl中从一个非常大的散列中获取一个键(随机ok)?,perl,hash,Perl,Hash,假设您有一个非常大的散列(许多键),并且有一个可能删除其中许多键的函数,例如: while ( each %in ) { push @out, $_; functionThatDeletesOneOrMoreKeys($_, \%in); } 我相信在这种情况下,each是从散列中提取单个键的有效方法,但是文档中说从散列中删除键时不应使用each 否则我可以使用while(%in){$\=(keys(%in))[0]…,但对于非常大的散列来说,这似乎效率非常低 有没有更好的方法可以做到

假设您有一个非常大的散列(许多键),并且有一个可能删除其中许多键的函数,例如:

while ( each %in ) {
  push @out, $_;
  functionThatDeletesOneOrMoreKeys($_, \%in);
}
我相信在这种情况下,
each
是从散列中提取单个键的有效方法,但是文档中说从散列中删除键时不应使用
each

否则我可以使用
while(%in){$\=(keys(%in))[0]…
,但对于非常大的散列来说,这似乎效率非常低


有没有更好的方法可以做到这一点?

在不了解您所指复杂性细节的情况下提供一般建议:


更改删除键的函数行,以将要删除的键存储在数组或散列(或文件)中。第一个循环完成后,循环通过该数组或散列(或文件)然后从第一个散列中删除这些键。

这似乎是一件可怕的事情,如果您解释一下您试图实现的目标会更好

但是,使用
each
进行迭代时删除散列元素的问题在于
each
为散列保留一个状态值,该状态值取决于保持不变的散列

您可以通过在同一哈希上调用
(或
)来清除该状态

下面是一个示例,该示例删除具有给定键的三个元素及其前后的元素,以尝试模拟您的
函数\u删除一个或多个\u键
(即应该调用的键)的功能

我建议您不要为此使用全局
$\ucode>变量

输出
或者如Borodin所示,每次您知道您至少删除了一个元素时,都会重置迭代器。

如果函数不依赖于$\ux,那么为什么要从循环中开始函数呢?最多,循环/函数应该捕获所有需要删除的键,然后在第一个循环外删除它们。很好,确实如此。我编辑了这个问题。当然,我真正的问题要复杂得多…这听起来像-你能在这里进一步澄清这个场景吗?我可能会想执行一个转换,但这完全取决于你试图完成什么。是的,我知道-真正的问题相当复杂,也就是说,我正在尝试例如,如果我输入“myfile_1,a”,“myfile_1,cat”,“myfile_2,a”和“myfile_2,cat”,我希望我的脚本返回“myfile_[12],{a,cat}”。这适用于任意复杂的列表项。每个列表项都是一个哈希键,我的子例程会在多维中查找连续的矩形块,并在删除时将其从哈希中删除。只要哈希不是空的并且以随机元素开始,外部循环就会继续。如果要删除,请参见我为什么尝试简化?;)对于当前元素,您不需要重置迭代器,因为这是显式安全的。如果您删除其他键,此解决方案很可能会导致无限循环。@ikegami:是的,我们必须假设OP的子例程会删除具有当前键的元素以及任何其他元素,否则将导致无限循环。@ikegami:虽然我无法在上面的程序中一次删除三个元素的
每个
,但即使没有调用
,也无法在哈希为空之前返回false。这似乎表现得非常好1)删除其他键可能会按需要进行,但文档明确禁止。它可能并不总是有效,或者可能会停止rking.2)但这不是我所说的。我的意思是,如果你在没有删除当前键的情况下通过一个过程(对于OP来说这听起来是可能的),这个解决方案将导致一个无穷大的错误loop@ikegami字体所有这些都非常清楚。看看我的评论
use strict;
use warnings 'all';
use feature 'say';

my %h = map +( $_ => 1), 0 .. 9;

while ( my $key = each %h ) {

    say $key;

    delete @h{$key-1, $key, $key+1};

    keys %h;     # Reset "each" state
}
2
9
4
6
0
my @in_keys = keys %in;
for (@in_keys)  {
    if (exists $in{$_}) {
        ...
    }
}