在迭代时我应该如何删除哈希元素?

Dav*_*d B 13 perl hash

我有相当大的哈希(大约10M键),我想从中删除一些元素.

我通常不喜欢使用deletesplice和我拉闸复制我想要什么,而不是删除的内容,我不知道.但是这一次,由于哈希是真正的大,我想我会直接将它删除.

所以我做的是这样的:

foreach my $key (keys %hash) {
 if (should_be_deleted($key)) {
  delete($hash{$key});
 }
}
Run Code Online (Sandbox Code Playgroud)

它似乎工作正常.但是..如果我想在迭代它们之前删除一些元素怎么办?我将通过例子解释:

foreach my $key (keys %hash) {
 if (should_be_deleted($key)) {
  delete($hash{$key});
  # if $key should be deleted, so does "$key.a", "kkk.$key" and some other keys
  # I already know to calculate. I would like to delete them now...
 }
}
Run Code Online (Sandbox Code Playgroud)

我想一些可能的解决方案 - 比如检查是否有键仍然存在,如在环或第一循环的第一步,创建密钥的列表中删除(并没有实际删除它们),则实际删除的另一个循环.

你对此有何看法?

UPDATE

似乎双通道方法已达成共识.但是,在第一遍中我仔细检查已经标记为删除的密钥,这是非常低效的.这有点递归,因为我不仅检查密钥,还计算应删除的其他密钥,尽管它们已经由原始密钥计算.

也许我需要使用一些更动态的数据结构来迭代密钥,这将动态更新?

Mic*_*man 8

我建议做两次通过,因为它更强大.散列顺序实际上是随机的,所以不能保证你会在相关的密钥之前看到"主要"密钥.例如,如果should_be_deleted()仅检测到不需要的主键并计算了相关的主键,则最终可能会处理不需要的数据.两遍方法避免了这个问题.

my @unwanted;
foreach my $key (keys %hash) {
    if (should_be_deleted($key)) {
         push @unwanted, $key;
         # push any related keys onto @unwanted
    }
}

delete @hash{@unwanted};

foreach my $key (keys %hash) {
    # do something
}
Run Code Online (Sandbox Code Playgroud)


Zai*_*aid 2

根据问题中的示例,您可以使用 agrep来过滤出与您的匹配的键$key

更新

您的评论已经阐明了您的需求。我的建议是确定符合您要求的索引并@keys相应地更新您设置。这个想法是@keys在循环的同时进行更新,以避免不必要的迭代。

我在这里将简单的 grep 实现为可自定义函数。

sub matches { $_[0] =~ /$_[1]/ ? 1 : 0 }  # Simple grep implemented here

my @keys = keys %hash;  # @keys should initially contain all keys

while ( @keys ) {

    my $key = shift @keys;
    next unless should_be_deleted ($key);  # Skip keys that are wanted

    my @indexes_to_delete = grep { matches ($key, qr/$keys[$_]/) } 0 .. $#keys;

    delete @hash { @keys[@indexes_to_delete] };     # Remove the unwanted keys

    splice @keys, $_, 1 foreach @indexes_to_delete; # Removes deleted ...
                                                    # ... elements from @keys.
                                                    # Avoids needless iterations.
}
Run Code Online (Sandbox Code Playgroud)