Динамическое создание хеша хэша в perl

Я пытаюсь создать хэш хэша - глубина вложенности зависит от количества аргументов, переданных в массив @aGroupByFields.

В приведенной ниже реализации я получаю желаемую хэш-структуру. Но я жестко запрограммировал поля [ пример - $phBugRecord->{createdBy} ] вместо того, чтобы получать их из массива.

Я не уверен, как динамически создать это.

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
    );

}

Любой указатель будет большим подспорьем. Спасибо.


person Soumya    schedule 16.03.2016    source источник
comment
Вы не хотите генерировать заявление. Вы хотите сгенерировать хэш. Но зачем тебе это?   -  person simbabque    schedule 16.03.2016
comment
Пожалуйста, обратитесь к следующему вопросу: stackoverflow.com/questions /4558981/ Надеюсь, это поможет!   -  person Yaswanth Gelli    schedule 16.03.2016
comment
См. Data::Diver и Deep::Hash::Utils   -  person Håkon Hægland    schedule 16.03.2016
comment
@simbabque: сгенерированный таким образом хеш будет использоваться для отображения отчета об ошибке. Затем отчет об ошибке сможет отображать ошибки, сгруппированные по типу createdBy › status › devPriority. [Короче говоря, мне дан список полей groupBy и дамп всех записей об ошибках, и мне нужно вернуть хэш, который должен соответствующим образом сгруппировать записи об ошибках]. В любом случае спасибо за редактирование. Ура.   -  person Soumya    schedule 16.03.2016
comment
Итак, вы хотите автоматически группировать.   -  person simbabque    schedule 16.03.2016
comment
@simbabque: Да, именно так. Количество полей groupBy непостоянно, поэтому я думаю, что эта автоматическая группа - лучший подход. Но если есть лучшие способы, я более чем готов изменить свой подход здесь.   -  person Soumya    schedule 16.03.2016
comment
@HåkonHægland Я не знал Data::Diver. Это весело, особенно то, что это может быть lvalue. :)   -  person simbabque    schedule 16.03.2016


Ответы (2)


Этот код сделает то, что вам нужно

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 } //= {};
        }
    }
}
person Borodin    schedule 16.03.2016
comment
Это сработало как волшебство. Вернуло мне именно то, что я хотел. Я знаю, что прошу здесь слишком много - не могли бы вы объяснить код $hash = $hash-›{ $key } //= {}; Большое спасибо за ваш вклад. - person Soumya; 19.03.2016

Вот рабочая реализация с 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;

Вывод выглядит так.

\ {
    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"
                }
            ]
        }
    }
}

Обратите внимание, что я переименовал ваши переменные. Читать такой код было очень тяжело. Имеет больше смысла просто использовать говорящие имена вместо загадочных сокращений для типа переменной. Сигил уже делает это за вас.

person simbabque    schedule 16.03.2016