Разобрать текстовый файл во вложенную структуру данных - PullRequest
0 голосов
/ 15 мая 2018

Это мой текстовый файл:

animal, cola, husband, 36 
animal, wilma, wife, 31
animal, pebbles, kid, 4
brutal, george, husband, 41
brutal, jane, wife, 39
brutal, elroy, kid, 9
cosa, homer, husband, 34
cosa, marge, wife, 37
cosa, bart, kid, 11

И это структура данных, которую я хочу:

%HASH = (
    animal  => [
        { name => "cola",    role => "husband", age  => 36, },
        { name => "wilma",   role => "wife",    age  => 31, },
        { name => "pebbles", role => "kid",     age  =>  4, },
    ],
    brutal  => [
        { name => "george",  role => "husband", age  => 41, },
        { name => "jane",    role => "wife",    age  => 39, },
        { name => "elroy",   role => "kid",     age  =>  9, },
    ],
    cosa  => [
        { name => "homer", role => "husband", age => 34, },
        { name => "marge", role => "wife",    age => 37, },
        { name => "bart",  role => "kid",     age => 11, },
    ],
);

У меня есть некоторые фрагменты кода, но я не могу их собратьв связный сценарий.Я хочу, чтобы только кто-то помог мне определить эту структуру и понять ее.

Ответы [ 2 ]

0 голосов
/ 15 мая 2018

У структуры данных, которую вы показываете, есть одно критическое правило: значение в хэше может быть только скалярным.

Таким образом, чтобы связать многозначную переменную с ключом, используйте ссылку на эту переменную, здесь arrayref. И если значения в этом массиве должны быть более сложными, чем скаляры, вы снова используете ссылку, здесь хеш-значение. & dagger; Таким образом, значением для каждого ключа является arrayref, элементы которого являются hashrefs.

Затем вам нужно узнать, как получить доступ к элементам глубже в структуре. Это тоже не очень сложно: разыменуйте их, и тогда вы сможете работать с ними, как если бы вы использовали массив или хеш.

Все это находится в perldsc , для которого нужно очистить с помощью perlreftut . Полная ссылка perlref .

Когда это используется в вашей проблеме

use warnings;
use strict;

use Data::Dump qw(dd);

my $file = 'data.txt';
open my $fh, '<', $file or die "Can't open $file: $!";

my %result;

while (<$fh>) {
    chomp;
    my ($key, $name, $role, $age) = split /\s*,\s*/;

    push @{$result{$key}}, { name => $name, role => $role, age => $age };   
}

dd \%result;

Это печатает правильную структуру данных. Обратите внимание на использование Data :: Dump для просмотра сложной структуры данных. Наиболее часто встречающийся модуль для этого - Data :: Dumper , но есть и другие.

В split выше в качестве разделителя используется регулярное выражение /\s*,\s*/, поэтому для разделения строки запятой необязательно в окружении пробелов. По умолчанию используется строка для разделения, которая составляет $_

Обратите внимание, что нам не нужно "добавлять ключ" или устанавливать его значение arrayref перед их использованием, как это делается с помощью autovivification . Смотрите, например, эту страницу и эту страницу и эту страницу . Это сложная функция, которая может укусить при неправильном использовании, поэтому, пожалуйста, прочтите ее.


& dagger; Если массивы или хэши указаны как "элементы" массива, они "сплющиваются" & ndash; их элементы объединяются со всеми другими заданными элементами, и весь совокупный список используется для заполнения массива, и мы получаем один массив со всеми этими элементами. Так

my @ary = 1..3;
my %hash = (a => 10, b => 20);
# Most likely an error:
my @all = (5, @ary, %hash, 100);  #--> (5, 1, 2, 3, a, 10, b, 20, 100)

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

Вместо этого мы берем ссылки на массивы и хэши и пишем

my @all = (5, \@ary, \%hash, 100);

Теперь содержимое @ary и %hash сохраняет свою индивидуальность и может быть восстановлено при необходимости.

0 голосов
/ 15 мая 2018
  1. Разбор каждой строки в хеш.
  2. Удалить ключевой столбец из хеша.
  3. Вставить хеш в массив на основе ключевого столбца.

Код:

use strict;
use warnings;

use Data::Dumper;

my %hash;
my @columns = qw(category name role age);

while (<DATA>) {
    chomp;
    my %temp;
    @temp{@columns} = split(/\s*,\s*/);

    my $key = delete($temp{category});
    push(@{$hash{$key}}, \%temp);
}

print Dumper(\%hash);

__DATA__
animal, cola, husband, 36
animal, wilma, wife, 31
animal, pebbles, kid, 4
brutal, george, husband, 41
brutal, jane, wife, 39
brutal, elroy, kid, 9
cosa, homer, husband, 34
cosa, marge, wife, 37
cosa, bart, kid, 11

Выход:

$VAR1 = {
          'cosa' => [
                      {
                        'name' => 'homer',
                        'age' => '34',
                        'role' => 'husband'
                      },
                      {
                        'name' => 'marge',
                        'age' => '37',
                        'role' => 'wife'
                      },
                      {
                        'name' => 'bart',
                        'age' => '11',
                        'role' => 'kid'
                      }
                    ],
          'brutal' => [
                        {
                          'name' => 'george',
                          'age' => '41',
                          'role' => 'husband'
                        },
                        {
                          'name' => 'jane',
                          'age' => '39',
                          'role' => 'wife'
                        },
                        {
                          'name' => 'elroy',
                          'age' => '9',
                          'role' => 'kid'
                        }
                      ],
          'animal' => [
                        {
                          'name' => 'cola',
                          'age' => '36',
                          'role' => 'husband'
                        },
                        {
                          'name' => 'wilma',
                          'age' => '31',
                          'role' => 'wife'
                        },
                        {
                          'name' => 'pebbles',
                          'age' => '4',
                          'role' => 'kid'
                        }
                      ]
        };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...