【问题标题】:perl group results in hash using fetchrow_hashrefperl 组使用 fetchrow_hashref 产生哈希
【发布时间】:2014-11-08 12:39:42
【问题描述】:

我想使用以下显示的数据按 countryid 对我的结果进行分组。

my @test = ();
my $st   = qq[
    SELECT id,countryID,abbrev
    FROM myTable
];
my $q = $data->prepare($st);
$q->execute() or query_error($st);
while ( my $result = $q->fetchrow_hashref ) {
    push @test, $result;
}

使用 fetchrow_hashref 显示结果没有问题

use Data::Dumper;
print STDERR Dumper(\@test);

返回

$VAR1 = [
    {   'id'        => '1',
        'countryID' => '1',
        'title'     => 'Title 1',
        'abbrev'    => 't1'
    },
    {   'id'        => '2',
        'countryID' => '2',
        'title'     => 'Title 2',
        'abbrev'    => 't2'
    },
    {   'id'        => '3',
        'countryID' => '3',
        'title'     => 'Title 3',
        'abbrev'    => 't3'
    },
    {   'id'        => '4',
        'countryID' => '1',
        'title'     => 'Title 4',
        'abbrev'    => 't4'
    }
];

我想按国家分组,如下所示。

$VAR1 = [
    'countries' => {
        '1' => [
            {   'id'     => '1',
                'title'  => 'Title 1',
                'abbrev' => 't1'
            },
            {   'id'     => '4',
                'title'  => 'Title 4',
                'abbrev' => 't4'
            }
        ],
        '2' => [
            {   'id'     => '2',
                'title'  => 'Title 2',
                'abbrev' => 't2'
            }
        ],
        '3' => [
            {   'id'     => '3',
                'title'  => 'Title 3',
                'abbrev' => 't3'
            }
        ]
    }
];

我怎样才能让它在 while 循环中工作?

【问题讨论】:

    标签: arrays perl hash multidimensional-array hashref


    【解决方案1】:

    像这样,输入/输出数据结构可能不是您所拥有或想要的,您可以对其进行修补。

    use strict;
    use Data::Dumper;
    
    $a = [
        {   'id'        => '1',
            'countryID' => '1',
            'title'     => 'Title 1',
            'abbrev'    => 't1'
        },
        {   'id'        => '2',
            'countryID' => '2',
            'title'     => 'Title 2',
            'abbrev'    => 't2'
        },
        {   'id'        => '3',
            'countryID' => '3',
            'title'     => 'Title 3',
            'abbrev'    => 't3'
        },
        {   'id'        => '4',
            'countryID' => '1',
            'title'     => 'Title 4',
            'abbrev'    => 't4'
        }
    ];
    
    my $b = {};
    
    for my $item (@$a) {
        if ( exists( $b->{ $item->{'countryID'} } ) ) {
            push( @{ $b->{ $item->{'countryID'} } }, $item );
        } else {
            $b->{ $item->{'countryID'} } = [$item];
        }
    }
    print Dumper($b);
    

    以上打印:

    $VAR1 = {
        '1' => [
            {   'abbrev'    => 't1',
                'title'     => 'Title 1',
                'id'        => '1',
                'countryID' => '1'
            },
            {   'abbrev'    => 't4',
                'title'     => 'Title 4',
                'id'        => '4',
                'countryID' => '1'
            }
        ],
        '3' => [
            {   'abbrev'    => 't3',
                'title'     => 'Title 3',
                'id'        => '3',
                'countryID' => '3'
            }
        ],
        '2' => [
            {   'abbrev'    => 't2',
                'title'     => 'Title 2',
                'id'        => '2',
                'countryID' => '2'
            }
        ]
    };
    

    【讨论】:

      【解决方案2】:

      你需要稍微修正你的语法(例如=>而不是= >),但是一旦你这样做了,这样的东西应该可以很好地工作。

      for (@$VAR1_orig) {
          my %a = %$_;
          my $countryID = $a{countryID};
          delete $a{countryID};
          push @{$VAR1->{countries}{$countryID}}, \%a;
      }
      

      (顺便说一下,我已经在我的电脑上试过了。它可以工作。)

      上面假设%$VAR1最初是空的,然后根据@$VAR1_orig填充它,之后你可以用$VAR1做任何你喜欢的事情。 (我假设你知道 %$@$ 在 Perl 中的含义,但这不是你可能知道的初学者主题。请参阅 man 1 perlref。)

      【讨论】:

        【解决方案3】:

        忽略示例数据结构中的错误,您基本上是在寻找将散列数组的散列转换为散列数组的散列。完成初始数据结构设置后,您可以执行以下操作来创建新的嵌套数据结构:

        for my $href ( @test ) {
            my $id = $href->{countryID};
            delete $href->{countryID};
            push @{ $test2->{countries}{$id} }, $href;
        }
        

        迭代数组@test 的每个元素,这基本上是一个哈希引用数组。创建一个变量$id,它将从哈希中捕获countryID 值。我们从哈希引用中删除它,然后将该哈希引用分配给我们的新嵌套数据结构,其中countries 作为第一级key$id 作为第二级键。

        我们使用push 语法来创建我们的此类引用数组。

        注意:正如 thb 在 cmets 中所述,这确实会破坏您的原始数据结构。如果您想保留原始结构,请将代码修改为以下内容:

        for my $href ( @test ) {
            my $copy = { %$href };
            my $id   = $copy->{countryID};
            delete $copy->{countryID};
            push @{ $test2->{countries}{$id} }, $copy;
        }
        

        【讨论】:

        • 你的回答很好,但我想说一句:除了填充%$test2,你的代码不会无意中垃圾@test吗?如果是这样,这可能很好,但也许应该指出。
        • 感谢@thb 的反馈。我已将您的评论添加到答案中,并建议了一种替代解决方案来回避该问题。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-28
        • 1970-01-01
        • 2020-07-19
        • 2017-02-24
        相关资源
        最近更新 更多