【问题标题】:Is this the cleanest way to extract an AoH subset in Perl?这是在 Perl 中提取 AoH 子集的最干净的方法吗?
【发布时间】:2011-12-28 01:47:07
【问题描述】:

出于好奇,还有其他方法可以提取我的 AoH 结构的子集吗? AoH 是“矩形”的(即保证在所有 hashref 中具有相同的键)。

使用临时变量和嵌套的maps 对于本质上是一个花哨的哈希切片来说似乎有点太多了:

use strict;
use warnings;
use Data::Dump 'dump';

my $AoH = [ # There are many more keys in the real structure

            { a => "0.08", b => "0.10", c => "0.25" },
            { a => "0.67", b => "0.85", c => "0.47" },
            { a => "0.06", b => "0.57", c => "0.84" },
            { a => "0.15", b => "0.67", c => "0.90" },
            { a => "1.00", b => "0.36", c => "0.85" },
            { a => "0.61", b => "0.19", c => "0.70" },
            { a => "0.50", b => "0.27", c => "0.33" },
            { a => "0.06", b => "0.69", c => "0.12" },
            { a => "0.83", b => "0.27", c => "0.15" },
            { a => "0.74", b => "0.25", c => "0.36" },
          ];

# I just want the 'a's and 'b's

my @wantedKeys = qw/ a b /;  # Could have multiple unwanted keys in reality

my $a_b_only = [
                  map { my $row = $_;
                        +{
                           map { $_ => $row->{$_} } @wantedKeys
                         }
                  }
                  @$AoH
               ];

dump $a_b_only; # No 'c's here

【问题讨论】:

  • 我想可能是这样,而且我怀疑如果你使用这样的矩形 AoH,你会经常这样做,所以我建议编写一个名为 project() 的函数来进行这种转换任意 AoH 和“列”列表。
  • 我同意 j_random_hacker:发布的解决方案看起来不错,但是通过将核心功能编写为单独的函数可以大大提高可读性。例如,select_from_hash(HASH_REF, ARRAY_REF_OF_WANTED_KEYS)

标签: perl data-structures


【解决方案1】:

这需要一个map 和一个任意键列表:

my @wantedKeys = qw/a b/;
my $wanted = [
    map { my %h; @h{@wantedKeys} = @{ $_ }{@wantedKeys}; \%h }  @$AoH
];

(在this post 的帮助下)

【讨论】:

    【解决方案2】:

    如果你不再需要$AoH,你可以使用破坏性的方式:

    delete $_->{c} for @$AoH;
    

    【讨论】:

    • 我有一个更通用的解决方案,我有多个我不想要的列。 'a','b', 'c' 示例只是为了减少冗长。
    • 一次可以删除多个键:delete @{ $_ }{qw/b c/} for @$AoH;
    • 是的。不过,看到一个非破坏性的替代方案会很有趣。
    • @Zaid: use Clone qw(clone); my $copy = clone $AoH; delete @{ $_ }{qw/b c/} for @$copy;
    • 解决需求而不是满足需求 ;)
    【解决方案3】:

    你想要delete

    my $foo = [ map { delete $_->{c}; $_  } @$AoH ];
    

    如果要保留原始数据,则需要先取消引用哈希。

    my $foo = [ map { my %hash = %$_; delete $hash{c}; \%hash; } @$AoH ];
    

    【讨论】:

    • 我有一个更通用的解决方案,我有多个我不想要的列。 'a','b', 'c' 示例只是为了减少冗长。
    【解决方案4】:

    这是我的解决方案(让我介绍一下漂亮的 Data::Printer 模块):

    use Modern::Perl;
    use Data::Printer { colored => 1 };
    
    my $AoH = [
                { a => "0.08", b => "0.10", c => "0.25" },
                { a => "0.67", b => "0.85", c => "0.47" },
                { a => "0.06", b => "0.57", c => "0.84" },
                { a => "0.15", b => "0.67", c => "0.90" },
                { a => "1.00", b => "0.36", c => "0.85" },
                { a => "0.61", b => "0.19", c => "0.70" },
                { a => "0.50", b => "0.27", c => "0.33" },
                { a => "0.06", b => "0.69", c => "0.12" },
                { a => "0.83", b => "0.27", c => "0.15" },
                { a => "0.74", b => "0.25", c => "0.36" },
              ];
    
    # I just want the 'a's and 'b's, so I build a new hash with the keys I want
    my @ab = map { {a=>$_->{a}, b=>$_->{b}} } @$AoH;
    p @ab;
    
    # If you don't mind remove the "c" key in your original structure:
    #  map { delete $_->{c} } @$AoH;
    #  and $AoH is an array of hashes without the "c" key.
    

    【讨论】:

    • 那里有有趣的模块!请注意,密钥本质上可能是动态的,因此我没有奢侈(也没有耐心)对密钥进行硬编码。
    猜你喜欢
    • 2012-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    相关资源
    最近更新 更多