【问题标题】:How can I reset a hash completely without using a for loop?如何在不使用 for 循环的情况下完全重置哈希?
【发布时间】:2011-04-18 03:41:20
【问题描述】:

我想完全重置我的%hash,使其完全不包含键或值。我更喜欢使用单线而不是必须使用循环。

到目前为止我已经尝试过:

%hash = 0;
%hash = undef;

但是这些都在启用警告的严格模式下抛出错误,所以我写了一个简单的 for 循环来实现同样的事情:

for (keys %hash) {
    delete $hash{$_};
}

这行得通,但我真的很想用单线来做到这一点。有没有办法简单地重置我忽略的哈希?

【问题讨论】:

  • 我很惊讶没有人已经提出过这个问题。 AFAICR 我从来不需要重置哈希,因为使用 Perl 可以有非常紧凑的范围。相反,我让变量简单地超出范围;如果在循环中,将在顶部附近使用my 创建一个新词法。 – 我认为这是一个 XY 问题,有算法改进的空间,或许可以提供更多上下文?
  • 哈希是一个全局的,我在所有检查和平衡之后在我的程序开始附近创建。它使用不同的子程序进行修改,直到我将最终版本分配到一个数组中。鉴于这个流程,除非我遗漏了什么,否则我相信在将它分配给数组之后“重置”这个特定的哈希比使用my 语句重新创建它更容易。 (我可能忽略了一个 XY 问题,因为我不知道如何执行重置哈希之类的操作)

标签: perl hash


【解决方案1】:

%hash = ();undef %hash; 都可以工作,不同的是后者会回馈一些内存用于其他事情。前者会将之前使用的哈希中的东西保留在内存中,假设以后无论如何都会在重新填充哈希时再次使用它。

您可以使用Devel::Peek 来观察该行为:

$ perl -MDevel::Peek -we'my %foo = (0 .. 99); %foo = (); Dump \%foo; undef %foo; Dump \%foo'
SV = IV(0x23b18e8) at 0x23b18f0
  REFCNT = 1
  FLAGS = (TEMP,ROK)
  RV = 0x23acd28
  SV = PVHV(0x23890b0) at 0x23acd28
    REFCNT = 2
    FLAGS = (PADMY,SHAREKEYS)
    ARRAY = 0x23b5d38
    KEYS = 0
    FILL = 0
    MAX = 63
    RITER = -1
    EITER = 0x0
SV = IV(0x23b18e8) at 0x23b18f0
  REFCNT = 1
  FLAGS = (TEMP,ROK)
  RV = 0x23acd28
  SV = PVHV(0x23890b0) at 0x23acd28
    REFCNT = 2
    FLAGS = (PADMY,SHAREKEYS)
    ARRAY = 0x0
    KEYS = 0
    FILL = 0
    MAX = 7
    RITER = -1
    EITER = 0x0

PVHVs 中的 MAX 字段是重要的位。

【讨论】:

  • 感谢您提供额外的见解。我希望我的哈希在重新填充时永远不会包含相同的值,所以我将使用 undef %hash;语法。
  • 这不是关于存储在哈希中的值,而是关于它们有多少。分配、释放,然后再次分配一些内存以将值存储在散列中并不是您能做的最快的事情,因此 perl 假设散列最终会再次增长到其原始大小,即使它被 @ 清除987654327@,并保留在散列中存储尽可能多的元素所需的内存,除非明确要求不要这样做。不要将这与您在哈希中的实际值占用的内存相混淆。
  • 现在我看到了不同之处。好的,我将不得不使用 Devel::Peek 来查看哪个对我的用例更有效。
  • 实际上,Devel::Peek 并不能告诉您什么更有效。这就是你的大脑的用途。如果你正在清除一个有 65 个成员的散列并且只是要放入 65 个成员,那么你最好只是重用内存。如果您正在清除一个包含超过 9000 个条目的哈希,并且只想拥有三个,那么确定...是时候清除它了。
【解决方案2】:

怎么样

%hash = ();

【讨论】:

    【解决方案3】:

    你可以使用undef

    undef %hash;
    

    【讨论】:

      【解决方案4】:

      你可以这样做:

      %hash = ();
      

      【讨论】:

        【解决方案5】:

        使用

        %hash = ();
        

        【讨论】:

        • 有了my,您实际上是在创建一个与现有哈希无关的新哈希,而不是清除旧哈希。
        【解决方案6】:

        %hash = ();必须工作

        【讨论】:

          【解决方案7】:

          由于 OP 要求使用一个可与 use strict 和 warnings 一起使用的衬线

          delete $hash{$_} for (keys %hash)
          

          【讨论】:

            猜你喜欢
            • 2010-11-17
            • 1970-01-01
            • 2011-02-22
            • 2017-03-30
            • 2021-07-14
            • 2011-04-03
            • 1970-01-01
            • 1970-01-01
            • 2023-02-05
            相关资源
            最近更新 更多