Creating hash of hash dynamically in perl

我与影子孤独终老i 提交于 2019-12-02 05:15:44

问题


I am trying to create a hash of hash of - the nesting depth depends on the number of arguments passed into @aGroupByFields array.

In the below implementation, I am getting the desired hash structure.But I have hard coded the fields [ example - $phBugRecord->{createdBy} ] instead of deriving it from the array.

I am not sure how to dynamically create this.

my (@aGroupByFields) = ['createdBy','status','devPriority']; 
# In real case,these are passed in as arguments

my (%hTemp); 
# This is the final hash which will be structured according to above fields

# %hBugDetails is the hash containing details of all bugs

foreach my $phBugRecord ( @{ $hBugDetails{records} } ) {

    # The below statement needs to be generated dynamically as 
    # opposed to the hard-coded values.
    push(
        @{
            $hTemp{ $phBugRecord->{createdBy} }{ $phBugRecord->{status} }
                { $phBugRecord->{devPriority} }
        },
        $phBugRecord
    );

}

Any pointer will be a great help.Thanks.


回答1:


This code will do what you need

my @aGroupByFields = qw/ createdBy status devPriority /;

my %hTemp;

for my $phBugRecord ( @{ $hBugDetails{records} } ) {

    my $hash = \%hTemp;

    for my $field ( @aGroupByFields ) {

        my $key = $phBugRecord->{$field};

        if ( $field eq $aGroupByFields[-1] ) {
            push @{ $hash->{ $key } }, $phBugRecord;
        }
        else {
            $hash = $hash->{ $key } //= {};
        }
    }
}



回答2:


Here is a working implementation with Data::Diver.

use strict;
use warnings;
use Data::Diver 'DiveVal';
use Data::Printer;

my %hBugDetails = (
    records => [
        {
            createdBy   => 'created_by1',
            status      => 'status1',
            devPriority => 'dev_priority1',
            foo         => 'foo1',
            bar         => 'bar1',
        },
        {
            createdBy   => 'created_by1',
            status      => 'status2',
            devPriority => 'dev_priority2',
            foo         => 'foo',
            bar         => 'bar',
        },
    ],
);

# we want to group by these fields
my @group_by = ( 'createdBy', 'status', 'devPriority' );

my $grouped_bugs = {};    # for some reason we need to start with an empty hashref
foreach my $bug ( @{ $hBugDetails{records} } ) {

    # this will auto-vivify the hash for us
    push @{ DiveVal( $grouped_bugs, map { $bug->{$_} } @group_by ) }, $bug;
}

p $grouped_bugs;

The output looks like this.

\ {
    created_by1   {
        status1   {
            dev_priority1   [
                [0] {
                    bar           "bar1",
                    createdBy     "created_by1",
                    devPriority   "dev_priority1",
                    foo           "foo1",
                    status        "status1"
                }
            ]
        },
        status2   {
            dev_priority2   [
                [0] {
                    bar           "bar",
                    createdBy     "created_by1",
                    devPriority   "dev_priority2",
                    foo           "foo",
                    status        "status2"
                }
            ]
        }
    }
}

Note that I renamed your variables. It was very hard to read the code like that. It makes more sense to just use speaking names instead of cryptic abbreviations for the type of variable. The sigil already does that for you.



来源:https://stackoverflow.com/questions/36033603/creating-hash-of-hash-dynamically-in-perl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!