【问题标题】:Perl - Create Array of Hashes based on Hash filterPerl - 基于哈希过滤器创建哈希数组
【发布时间】:2018-08-26 20:38:06
【问题描述】:

我有这个包含一些信息的哈希:

my %hash = (
    key_1 => {
        year => 2000,
        month => 02,
    }, 
    key_2 => {
        year => 2000,
        month => 02,
    }, 
    key_3 => {
        year => 2000,
        month => 03,
    }, 
    key_4 => {
        year => 2000,
        month => 05,
    }, 
    key_5 => {
        year => 2000,
        month => 01,
    }
);

我不想创建一个散列数组,其中每个数组元素列出具有相同年份和月份的每个散列键/值对。

所以基本上我想创建这样的东西:

$VAR1 = [
    'key_1' => {
        'month' => 2,
        'year' => 2000
    },
    'key_2' => {
        'month' => 2,
        'year' => 2000
    }
], [
    'key_3' => {
        'month' => 3,
        'year' => 2000
    }
], [
    'key_4' => {
        'month' => 3,
        'year' => 2000
    }
], [
    'key_5' => {
        'year' => 2000,
        'month' => 1
    }
];

这里真正的问题是:如何将哈希键键值与其他键键值进行比较并从中制作映射。

感谢您的宝贵时间! =)

【问题讨论】:

  • 那么为什么在您的示例中 key_3 和 key_4 没有放在同一个数组中,因为它们的年份和月份相同?
  • 你说要创建的不是哈希数组,它是 hash 的哈希。您所谓的外部“列表”的成员是键值对,因此外部结构是一个有,而不是一个列表。
  • 你说你想要$VAR1 = [$k,$v,$k,$v...], [...], [...], ...;,这没有意义。接受的答案假设你的意思是你想要$VAR1 = [ [$k,$v,$k,$v,...], [...], [...], ... ];,但$VAR1 = [ { $k=>$v,$k=>$v,...}, {...}, {...}, ... ]; 不是更有意义吗?
  • @KjetilS。我修好了,我的错。

标签: arrays perl dictionary hash hashref


【解决方案1】:

我得到的结果略有不同 - key_3 和 key_4 应该属于同一组。

my %by_year_and_month;
undef $by_year_and_month{ $hash{$_}{year} }{ $hash{$_}{month} }{$_}
    for keys %hash;

my $result;
for my $year (keys %by_year_and_month) {
    for my $month (keys %{ $by_year_and_month{$year} }) {
        push @$result, [ map { $_ => { month => $month, year => $year } }
                         keys %{ $by_year_and_month{$year}{$month} } ];
    }
}

【讨论】:

  • 是的,你没看错,key_3和key_4应该属于同一个组!谢谢你的回答!
【解决方案2】:
my %hash = (
    key_1 => {year => 2000, month => 02},
    key_2 => {year => 2000, month => 02},
    key_3 => {year => 2000, month => 03},
    key_4 => {year => 2000, month => 03},
    key_5 => {year => 2000, month => 01}
);
my @v=qw(year month);             # keys compared
my @k=sort keys %hash;
my(@a,%i);
push@{$a[sub{$i{join$;,map$_[0]{$_},@v}//=@a}->($hash{$_})]},($_=>$hash{$_}) for@k;
use Data::Dumper; print Dumper(\@a);

【讨论】:

    【解决方案3】:

    你说你想要以下,但这没有意义。

     $VAR1 = [$k,$v,$k,$v...], [...], [...], ...;
    

    接受的答案假设您的意思是您想要以下内容:

    $VAR1 = [ [$k,$v,$k,$v,...], [...], [...], ... ];
    

    可以得到如下:

    sub group_id { sprintf "%04d-%02d", @{ $_[0] }{qw( year month )} }
    
    my %grouped;
    for my $k (keys(%hash)) {
       my $v = $hash{$k};
       push @{ $grouped{ group_id($v) } }, $k, $v;
    }
    
    my $VAR1 = [ map { $grouped{$_} } sort keys %grouped ];
    

    但这是一种非常奇怪的格式。以下会更有意义:

    $VAR1 = [ { $k=>$v,$k=>$v,...}, {...}, {...}, ... ];
    

    可以得到如下:

    sub group_id { sprintf "%04d-%02d", @{ $_[0] }{qw( year month )} }
    
    my %grouped;
    for my $k (keys(%hash)) {
       my $v = $hash{$k};
       $grouped{ group_id($v) }{$k} = $v;
    }
    
    my $VAR1 = [ map { $grouped{$_} } sort keys %grouped ];
    

    在这两种情况下,关键是使用哈希对相似的事物进行分组。

    在这两种情况下,生成的组都按时间顺序排列。

    【讨论】:

      猜你喜欢
      • 2011-04-20
      • 2013-12-20
      • 2011-05-08
      • 2015-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-19
      相关资源
      最近更新 更多