Заполнить хэш хэшей в Perl

Я хочу знать, как заполнить следующую хеш-структуру:

my $hash = {
    'user' => [
        {
            'id' => '1',
            'name' => 'John'
        },
        {
            'id' => '2',
            'name' => 'Pat'
        }

    ]
};

Я хочу иметь возможность динамически заполнять этот хэш. Я хочу перебирать значения из моей базы данных и добавлять (добавлять) новые значения (идентификатор, имя), чтобы заполнить хэш.


person Mark Marina    schedule 22.02.2012    source источник
comment
@Benoit: На самом деле неправильно, он использует анонимную хеш-ссылку. Он мог бы использовать my %hash = (...);   -  person Platinum Azure    schedule 22.02.2012
comment
Как именно выглядят значения из вашей базы данных? Большинство API-интерфейсов уровня данных уже возвращают данные в именно этом формате, поэтому вам не нужно ничего делать.   -  person DVK    schedule 22.02.2012


Ответы (3)


Чтобы заполнить значение в хеше хэшей, можно просто использовать:

my %hash;
....
$hash{$key}{$subkey} = $value;

Однако будьте осторожны, проходя через них! Скалярное значение $hash{$key} на самом деле будет скалярной ссылкой на вложенный хэш, а не на сам объект вложенного хеша.

person asf107    schedule 22.02.2012
comment
Он использует хэш-ссылку, так что это должно быть $hash->{$hey}{$subkey} = $value; - person Platinum Azure; 22.02.2012
comment
честно говоря, я честно предположил, что он имел в виду %hash себя :) - person asf107; 22.02.2012
comment
Спасибо Platinum Azure и asf107. Поскольку я динамически заполняю этот хэш, как добавить новые значения? Вот мой код. Как видите, это не сработает, потому что предыдущее значение всегда перезаписывается. foreach my $user (@users) { $hash-›{user}{id} = $user[0]; $hash-›{user}{name} = $user[1]; } Спасибо - person Mark Marina; 22.02.2012
comment
Как заполняется @users? это анонимный массив или значения? Если его значения, вам нужно будет использовать цикл while или цикл for, где вы управляете пошаговым выполнением. Это @users = ('John',1,'Pat',2) или @users = (['John',1],['Pat',2])? - person Rich; 23.02.2012
comment
код foreach my $user (@users) просто даст вам цикл, в котором на каждой итерации переменная $user будет принимать скалярное значение $users[0], $users[1], ... и т. д. Какой тип данных $user[0]? - person asf107; 23.02.2012

Чтобы добавить еще один элемент в эту структуру:

# Get the element
my $hashRef = {
    'id' => '1',
    'name' => 'John'
};
# You didn't specify what you have as far as DB data
my $hashRef = someMethodReturningDatabaseData(); 

# Add to the arrayref:
my $hash = { user => [] }; # Initialize - only once
$hash->{user} ||= []; # As alternative, always make sure to have an arrayref,
                      # on every iteration
# Add to the array ref
push @{ $hash->{user} }, $hashRef;

Основываясь на вашем комментарии к другому ответу, вы можете сделать

my $hash = { user => [] }; # Initialize - only once
foreach my $user (@users) {
    push @{ $hash->{user} }, { id => $user->[0], name => $user->[1] };
}

В качестве примечания, ваша структура данных выглядит очень странно - непонятно, зачем вам нужен внешний хэш всего с одним жестко запрограммированным ключом "user".

person DVK    schedule 22.02.2012
comment
+1 за ||=. Кстати, начиная с Perl 5.14 разыменование массива ref больше не требуется (perldoc.perl .org/functions/push.html). - person Martin; 22.02.2012
comment
@Martin, возможно, но это экспериментально и содержит ошибки (работает не на всех массивах, не автооживляется). - person ikegami; 23.02.2012
comment
Вам нужно изменить $user->[0] и $user->[1]. Когда я тестировал это ранее, я думал, что это новая функция. :) - person Rich; 23.02.2012

    my $user = {
        id   => $id,
        name => $name,
    };

    push @{ $hash->{user} }, $user;

Нит: $hash->{user} должно называться $hash->{users}

person ikegami    schedule 22.02.2012