перебор массива данных / хэшей - PullRequest
2 голосов
/ 26 октября 2011

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

Цель состоит в том, чтобы перечислить корневой / базовый путь, а затем перечислить все вложенные элементы path, если они существуют, и для каждого существующего вложенного элемента path перечислить file из этого вспомогательного пути.

Я знаю, что это, вероятно, требует прохождения через HoH или AoH. Может кто-нибудь показать мне методы Perl для этого? Спасибо.

Базовый уровень: / work / eng / feeds

 $VAR1 = {
              'recursive' => 'no',
              'version' => '0.20.202.1.1101050227',
              'time' => '2011-10-26T00:20:18+0000',
              'filter' => '.*',
              'path' => '/work/eng/feeds',
              'directory' => [
                             {
                               'owner' => 'tst_act',
                               'group' => 'eng',
                               'permission' => 'drwxrwxr-x',
                               'path' => '/work/eng/feeds',
                               'accesstime' => '1970-01-01T00:00:00+0000',
                               'modified' => '2011-08-27T03:13:53+0000'
                             },
                             {
                               'owner' => 'tst_act',
                               'group' => 'eng',
                               'permission' => 'drwxr-xr-x',
                               'path' => '/work/eng/feeds/customer_care',
                               'accesstime' => '1970-01-01T00:00:00+0000',
                               'modified' => '2011-10-25T23:54:17+0000'
                             }
                           ],
              'exclude' => ''
            };

Следующий уровень: / work / eng / feeds / customer_care

$VAR1 = {
          'recursive' => 'no',
          'version' => '0.20.202.1.1101050227',
          'time' => '2011-10-26T00:21:06+0000',
          'filter' => '.*',
          'path' => '/work/eng/feeds/customer_care',
          'directory' => [
                         {
                           'owner' => 'tst_act',
                           'group' => 'eng',
                           'permission' => 'drwxr-xr-x',
                           'path' => '/work/eng/feeds/customer_care',
                           'accesstime' => '1970-01-01T00:00:00+0000',
                           'modified' => '2011-10-25T23:54:17+0000'
                         },
                         {
                           'owner' => 'tst_act',
                           'group' => 'eng',
                           'permission' => 'drwx------',
                           'path' => '/work/eng/feeds/customer_care/abc',
                           'accesstime' => '1970-01-01T00:00:00+0000',
                           'modified' => '2011-10-25T17:12:56+0000'
                         },
                         {
                           'owner' => 'tst_act',
                           'group' => 'eng',
                           'permission' => 'drwx------',
                           'path' => '/work/eng/feeds/customer_care/def',
                           'accesstime' => '1970-01-01T00:00:00+0000',
                           'modified' => '2011-10-25T21:05:50+0000'
                         },
                         {
                           'owner' => 'tst_act',
                           'group' => 'eng',
                           'permission' => 'drwx------',
                           'path' => '/work/eng/feeds/customer_care/test',
                           'accesstime' => '1970-01-01T00:00:00+0000',
                           'modified' => '2011-10-25T21:28:14+0000'
                         }
                       ],
          'exclude' => ''
        };

Еще один уровень: / work / eng / feeds / customer_care / test (здесь файл существует)

$VAR1 = {
          'recursive' => 'no',
          'version' => '0.20.202.1.1101050227',
          'time' => '2011-10-26T00:30:02+0000',
          'filter' => '.*',
          'file' => {
                    'owner' => 'tst_act',
                    'replication' => '3',
                    'blocksize' => '134217728',
                    'permission' => '-rw-------',
                    'path' => '/work/eng/feeds/customer_care/test/q_data_20111023.dat',
                    'modified' => '2011-10-26T00:29:46+0000',
                    'size' => '379085',
                    'group' => 'eng',
                    'accesstime' => '2011-10-26T00:29:46+0000'
                  },
          'path' => '/work/eng/feeds/customer_care/test',
          'directory' => {
                         'owner' => 'tst_act',
                         'group' => 'eng',
                         'permission' => 'drwx------',
                         'path' => '/work/eng/feeds/customer_care/test',
                         'accesstime' => '1970-01-01T00:00:00+0000',
                         'modified' => '2011-10-26T00:29:46+0000'
                       },
          'exclude' => ''
        };

Ответы [ 2 ]

3 голосов
/ 26 октября 2011

Вот стартер:

sub list_path_files {
    my ($data) = @_;

    say $data->{path}; # get value from a hashref

    my @directories;
    # check whether it is a single value or an arrayref of values
    if (ref $data->{directory} eq 'ARRAY') {
        @directories = @{ $data->{directory} }; # dereference the arrayref to get an AoH
    } else {
        @directories = $data->{directory}; # just get the single value
    }

    for my $dir (@directories) {
        next if $dir->{path} eq $data->{path};
        say $dir->{path};
    }

    # I'll leave the rest for you to do
}

Обновление:

Чтобы перебрать хэш-ссылку, сначала нужно разыменовать его, а затем использовать функции each, keys или values:

%hash = %$VAR1; # dereference

while (my ($key, $value) = each %hash) {...}

for my $key (keys %$VAR1) {
    my $value = $VAR1->{$key};
}

for my $value (values %$VAR1) {...}

Вам также потребуется разыменовать значение хеша, если оно является вложенной структурой:

if (ref $val eq '') {
    # $val is just a scalar - don't need to deref
}
elsif (ref $val eq 'HASH') {
    my %hash = %$val;
}
elsif (ref $val eq 'ARRAY') {
    my @array = @$val;
}
0 голосов
/ 26 октября 2011

Поскольку в данных есть временные метки в стиле XML, а структуры каталогов / файлов представляют собой хэш или массив хэшей, я собираюсь предположить, что вы анализируете XML для создания исходного хэша?

Если вы используете XML :: Simple для чтения этого из XML,

ForceArray => ['directory', 'file']

избавит от необходимости проверять типы ссылок.

Затем вы можете упростить что-то вроде этого:

my %fs

for my $item (values %your_giant_hash_with_fs_data) {

    $fs{$_->{path}}='d' for ( @{ $item->{directory} } );
    $fs{$_->{path}}='f' for ( @{ $item->{file} } );

}

my $search_path='/work/eng/feeds/customer_care/test';
my $search=qr/^$search_path/;

for (sort keys %fs) {

    print "$fs{$_} $_\n" if /$search/;

}

Вывод:

d /work/eng/feeds/customer_care/test
f /work/eng/feeds/customer_care/test/q_data_20111023.dat

или если вы не хотите создавать временную структуру

my $search_path='/work/eng/feeds/customer_care/test';
my $search=qr/^$search_path/;

{
    my %seen;
    for my $item (values %your_giant_hash_with_fs_data) {
        for my $type (qw/directory file/) {
            for ( @{ $item->{$type} } ) {

                if ( $_->{path}=~/$search/ and not $seen{$_->{path}} ) {

                    printf("%-10s%s\n",$type,$_->{path});
                    $seen{$_->{path}}=1;

                }

            }
        }
    }
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...