Как перебрать YAML, сделайте c в perl после сохранения в хэш-памяти - PullRequest
0 голосов
/ 20 апреля 2020

Мне нужно обработать документ YAML:

sheet : filename.exe

book : bookname

characters :

   - amy : mother

   - mark : father

   - dave : son

Теперь у меня есть следующий код, в котором я хочу выполнить итерацию и сохранить «символ» в га sh для использования позже:

use YAML qw(LoadFile);
my $config = LoadFile('config.yaml');
my %charlist = ();
foreach my $key (keys %$config){
  next if ($key ne "character");
  foreach my $list (keys %{$config{$key}}){
    my $current_character = $config{$key}{$list};
    $charlist->{$list} = $current_character;
  }
}

Я пытаюсь сохранить его в ха sh следующим образом:

{ amy => mother,
  mark => father,
  dave => son
}

Я не могу go во второй foreach l oop. Я не могу понять проблему.

Ответы [ 2 ]

1 голос
/ 20 апреля 2020

ВСЕГДА используйте use strict; use warnings; (или эквивалентный). Это вызвало бы некоторые проблемы.


Ваш вопрос не имеет никакого отношения к YAML. Речь идет о навигации по структуре данных, создаваемой YAML. Итак, давайте начнем с использования следующего, чтобы узнать больше о структуре данных:

use Data::Dumper;
print(Dumper($config));

Мы получаем:

$VAR1 = {
          'sheet' => 'filename.exe',
          'book' => 'bookname',
          'characters' => [
                            {
                              'amy' => 'mother'
                            },
                            {
                              'mark' => 'father'
                            },
                            {
                              'dave' => 'son'
                            }
                          ]
        };

Мы заботимся только о $config->{characters}, который является справочным в массив (как показано []), поэтому мы будем иметь что-то следующего вида:

my %characters;
for (@{ $config->{characters} }) {
   ...
}

Каждый элемент массива - это ha sh, содержащий один символ. Мы можем использовать %h = (%h, %extra); для объединения.

my %characters;
for my $character_container (@{ $config->{characters} }) {
   %characters = ( %characters, %$character_container);
}

Альтернатива:

my %characters;
for my $character_container (@{ $config->{characters} }) {
   @characters{ keys(%$character_container) } = values(%$character_container);
}

Вот и все!


Обратите внимание, что формат вашего файла довольно странный. Это должно быть:

sheet : filename.exe

book : bookname

characters :

   amy : mother

   mark : father

   dave : son

Это дает

$VAR1 = {
          'book' => 'bookname',
          'characters' => {
                            'mark' => 'father',
                            'dave' => 'son',
                            'amy' => 'mother'
                          },
          'sheet' => 'filename.exe'
        };

И решение становится

my $characters = $config->{characters};

Хорошо, возможно, ваш вопрос как-то связан с YAML после всех :)


@ tooli c * одобряет использование

foreach my $key (keys %{ $config }) {
    next if ($key ne "characters");
    ...$config->{$key}...
}

Но это особенно плохой способ написания

if ( my $characters = $config->{$key} ) {
  ...$characters...
}

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

1 голос
/ 20 апреля 2020

Если бы у вас было use strict;, вы бы увидели несколько ошибок компиляции.

Я использовал Data::Dumper, чтобы посмотреть на структуру, возвращаемую LoadFile, чтобы упростить разыменование структуры. characters хранятся в виде массива, а не ха sh. Вы также пытались получить доступ к config как ha sh вместо хэш-ссылки.

Кроме того, perlds c является отличным источником для понимания ссылок.

use warnings;
use strict;
use YAML qw(LoadFile);
use Data::Dumper;
$Data::Dumper::Sortkeys = 1; 

my $config = LoadFile('config.yaml');

my %charlist;
foreach my $key (keys %{ $config }){
    next if ($key ne "characters");
    foreach my $list (@{ $config->{$key} }){
        %charlist = (%charlist, %{ $list });
    }
}

print Dumper(\%charlist);
...