Как я могу удалить пустые массивы / ссылки из хэша Perl? - PullRequest
2 голосов
/ 25 сентября 2010

Допустим, у меня есть следующий хэш Perl:

%hash = ( 
    'A' => { 
        'B' => ['C', 'D', 'E'], 
        'F' => { 'G' => [], 'H' => [] }, 
        'I' => [] 
        } );

и я хотел бы избавиться от [], чтобы получить результат хеширования ниже:

%hash = ( 
    'A' => [ 
       'B' => ['C', 'D', 'E'], 
       'F' => [ 'G', 'H', 'I' ] 
        ] 
    )

(я надеюсь, что мои {} и [] сбалансированы, мои извинения, если нет, но) по сути, я хотел бы сделать так, чтобы не было пустых массивов / ссылок. Я уверен, что это возможно / просто, но я не уверен, будет ли работать delete(), или есть лучший метод или модуль Perl. Может ли кто-нибудь направить меня в правильном направлении?

Ответы [ 3 ]

5 голосов
/ 25 сентября 2010

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

use Data::Visitor::Callback;
use List::MoreUtils 'all';

my $visitor = Data::Visitor::Callback->new(
    hash => sub {
        my ($self, $href) = @_;

        # fold hashrefs with only empty arrayrefs as values into arrayrefs
        if (all { ref $_ eq 'ARRAY' && !@{ $_ } } values %{ $href }) {
            return [ keys %{ $href } ];
        }

        # strip k/v pairs with an empty arrayref as a value
        return {
            map {
                $_ => $href->{$_}
            } grep {
                ref $href->{$_} ne 'ARRAY' || @{ $href->{$_} }
            } keys %{ $href }
        };
    },
);

my %new_hash = %{ $visitor->visit(\%hash) };

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

1 голос
/ 25 сентября 2010

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

Является ли ваш ожидаемый результат тем, что вы хотели?Кажется, это отличается от того, что вы сказали в тексте, как FM говорит .Я использую его хеш в своем примере.

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

#!perl
use strict;
use warnings;
use 5.010;

my %hash = ( # From FM
    'A' => {
        'B' => ['C', 'D', 'E'],
        'F' => {
            'G' => [],
            'H' => [],
            'Z' => ['FOO', 'BAR'],  # Not in the OP's original.
        },
        'I' => [],
    },
);

my @queue = ( \%hash );

while( my $ref = shift @queue ) {
     next unless ref $ref eq ref {};

     KEY: foreach my $key ( keys %$ref ) {
        if( ref $ref->{$key} eq ref {} ) {
            push @queue, $ref->{$key};
            next KEY;
            }
        elsif( ref $ref->{$key} eq ref [] ) {
            delete $ref->{$key} if @{$ref->{$key}} == 0;
            }
        }
     }

use Data::Dumper;
print Dumper( \%hash );

Мой вывод:

$VAR1 = {
          'A' => {
                   'F' => {
                            'Z' => [
                                     'FOO',
                                     'BAR'
                                   ]
                          },
                   'B' => [
                            'C',
                            'D',
                            'E'
                          ]
                 }
        };

Этот вывод звучит больше как то, что вы просите, а не как указанная вами реорганизация.Вы можете уточнить вывод?

1 голос
/ 25 сентября 2010

[Это должен быть комментарий, но мне нужно форматирование.]

Ваш вопрос озадачивает.(1) По какому принципу ключ I (из исходного хэша) попадает в список для ключа F (в ожидаемом хеше)?(2) И что должно произойти, если F будет содержать что-то, кроме пустых ссылок на массивы (см. Мое добавление к исходному хешу)?

my %hash_orig = (
    'A' => {
        'B' => ['C', 'D', 'E'],
        'F' => {
            'G' => [],
            'H' => [],
            'Z' => ['FOO', 'BAR'],  # Not in the OP's original.
        },
        'I' => [],
    },
);

my %hash_expected = (
    'A' => [
        'B' => ['C', 'D', 'E'],
        'F' => [ 'G', 'H', 'I'],    # Where should the Z info go?
    ],
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...