Доступ к многомерному хешу с использованием строк - PullRequest
0 голосов
/ 26 февраля 2019

У меня большой многомерный хеш, который является импортом структуры JSON.

my %bighash;

В% bighash есть элемент с именем:

$bighash{'core'}{'dates'}{'year'} = 2019.

У меня естьотдельная строковая переменная с именем core.dates.year, которую я хотел бы использовать для извлечения 2019 из% bighash.

Я написал этот код:

my @keys  = split(/\./, 'core.dates.year');
my %hash = ();
my $hash_ref = \%hash;

for my $key ( @keys ){
    $hash_ref->{$key} = {};
    $hash_ref = $hash_ref->{$key};
}

, который при выполнении:

say Dumper \%hash;

выходы:

$VAR1 = {
          'core' => {
                   'dates' => {
                             'year' => {}
                           }
                 }
        };

Пока все хорошо.Но теперь я хочу сказать:

print $bighash{\%hash};

Что я хочу вернуть 2019. Но ничего не возвращается, или я вижу ошибку об «Использование неинициализированного значения в% bighash в конкатенации (.) или строка в script.pl, строка 1371, строка 17 (# 1) ...

Может ли кто-нибудь указать мне на то, что происходит?

Мой проект предусматривает встраивание строк во внешнийфайл, который затем заменяется фактическими значениями из% bighash, так что это просто интерполяция строк.

Спасибо!

Ответы [ 3 ]

0 голосов
/ 26 февраля 2019

В Perl нет многомерных хэшей.Хэши - это пары ключ / значение.Ваше понимание структур данных Perl является неполным.

Переосмыслите вашу структуру данных следующим образом

my %bighash = (
    core => {
        dates => {
            year => 2019,
        },
    },
);

Существует разница между круглыми скобками () и фигурными скобками {},Символ % в имени переменной указывает, что это хэш, то есть набор неупорядоченных пар ключ / значение.Раунд () - это список.Внутри этого списка находятся два скалярных значения, то есть ключ и значение.Значение является ссылкой на другой, анонимный хеш.Вот почему он имеет вьющиеся {}.

Каждый из этих уровней является отдельной, отдельной структурой данных.

Это переписывание вашего кода похоже на то, что ikegami написал в своем ответе, но менее эффективно и более многословно.

my @keys = split( /\./, 'core.dates.year' );

my $value = \%bighash;
for my $key (@keys) {
  $value //= $value->{$key};
}

print $value;

Он шаг за шагом углубляется в структуру и в конечном итоге дает вам окончательное значение.

0 голосов
/ 26 февраля 2019

Hash::Fold может показаться полезным здесь.Вы можете «сгладить» свой хеш, а затем получить доступ ко всему с помощью одного ключа.

use Hash::Fold 'flatten';
my $flathash = flatten(\%bighash, delimiter => '.');
print $flathash->{"core.dates.year"};
0 голосов
/ 26 февраля 2019

Может ли кто-нибудь указать мне на то, что происходит [когда я использую $bighash{\%hash}]?

Хеш-ключи - это строки, а строковое значение \%hash это что-то вроде HASH(0x655178).Единственный элемент в %bighash имеет core - не HASH(0x655178) - для ключа, поэтому поиск по хешу возвращает undef.


Полезные инструменты:

sub dive_val :lvalue { my $p = \shift; $p //= \( $$p->{$_} ) for @_; $$p }   # For setting
sub dive { my $r = shift; $r //= $r->{$_} for @_; $r }                       # For getting

dive_val(\%hash, split /\./, 'core.dates.year') = 2019;
say dive(\%hash, split /\./, 'core.dates.year');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...