【问题标题】:How do I filter out empty hashes from an array in perl?如何从 perl 中的数组中过滤出空哈希?
【发布时间】:2012-09-20 01:50:35
【问题描述】:

我有一个这样的哈希数组:

my @array = [
             {1 => "Test1"},
             {},
             {1 => "Test2"},
            ];

我尝试从该数组中过滤掉 {},以便最终结果是一个没有任何 {} 的数组,如下所示:

my @array = [
             {1 => "Test1"},
             {1 => "Test2"},
            ];

我尝试使用类似的东西,但它不起作用:

my @new_array = grep(!/{}/, @array);

【问题讨论】:

  • 如果你真的想要一个只有一个元素的数组,那么解决方案就是my @new_array = map [ grep %$_, @$_ ], @array;。不过,我对此表示怀疑。

标签: arrays perl hash grep


【解决方案1】:

grep 命令可以将正则表达式作为参数,也可以是任意代码块。请不要尝试将 Perl 代码与正则表达式匹配,这是行不通的。

相反,我们要求匿名哈希中的键数:

my @new_array = grep { keys %$_ } @array;

这会选择@array 中键数不为零的所有哈希。

【讨论】:

  • +1。您可以在此处省略 scalar,但它可以使代码更加清晰。
  • 我实际上认为没有标量会更清晰......无论如何,grep 块总是被解释为布尔值。
  • @Dondi Michael Stroma,嗯,这让我想知道...%$_ 在布尔上下文中是特殊的(比在其他标量上下文中更有效)。我想知道是否将 grep 回调结果计为布尔值。如果是这样,你可以放弃keys。从技术上讲,你可以放弃keys,这只是效率问题。
  • @ikegami 我认为键是必需的,但我想不是。不过,它似乎更快。 Benchmark: timing 10000000 iterations of with_keys, without_keys... with_keys: 8 wallclock secs ( 8.59 usr + 0.01 sys = 8.60 CPU) @ 1162790.70/s (n=10000000) without_keys: 25 wallclock secs (25.05 usr + 0.03 sys = 25.08 CPU) @ 398724.08/s (n=10000000)
  • @Dondi Michael Stroma,根据perl5120delta将优化添加到5.12.0。
【解决方案2】:

1) 一个小的修正:

my @array = [
    {1 => "Test1"},
    {},
    {1 => "Test2"},
];

实际上是一个包含数组 ref 的 1 元素数组。你可能需要

my @array = (
    {1 => "Test1"},
    {},
    {1 => "Test2"},
);

2) grep 表达式:

my @new_array = grep { scalar %$_ } @array;

如果它为空,Hash 在标量上下文中返回 0,否则返回类似于 "17/32" 的值。所以grep 只会选择非空数组。

更新:正如@raina77ow 所建议的,标量可以省略!所以它甚至更短(虽然我仍然更喜欢明确的scalar,以便在 my 代码中清晰)。

my @new_array = grep { %$_ } @array;

【讨论】:

  • 甚至my @new_array = grep %$_, @array; :)
  • 我想知道人们一直在使用foo() if bar();foo() for bar(); 时对grep 的表达形式有什么问题。
【解决方案3】:

你需要这样的东西:

my @new_array = grep(keys %$_, @array);

您代码中的/.../ 是一个正则表达式。它检查数组中的每个元素是否包含某些字符。但是,您的数组包含对哈希的引用,因此您需要取消对每个元素的引用,然后查看它是否为空。

另外,这个声明是不正确的:

my @array = [
             {1 => "Test1"},
             {},
             {1 => "Test2"},
            ];

括号创建一个数组引用,而您只需要一个数组。只需使用括号代替:

my @array = (
             {1 => "Test1"},
             {},
             {1 => "Test2"},
            );

【讨论】:

    猜你喜欢
    • 2011-04-20
    • 1970-01-01
    • 1970-01-01
    • 2018-08-26
    • 2019-05-21
    • 2015-06-26
    • 1970-01-01
    • 2012-09-14
    • 1970-01-01
    相关资源
    最近更新 更多