2014-12-23 3 views
1

Ниже скрипт выведетКак получить данные :: Diver для создания массивов?

$VAR1 = { 
      'tank' => { 
         'fs' => { 
           'fs2b' => undef, 
           'fs2a' => undef, 
           'fs2c' => undef 
           } 
        } 
     }; 

, где я действительно хотел хэш хэш массива, как этот

$VAR1 = { 
      'tank' => { 
         'fs' => [ 
           'fs2a', 
           'fs2b', 
           'fs2c' 
           ] 
        } 
     }; 

Вопрос

Как бы это быть сделано с Data::Diver?

#!/usr/bin/perl 
use strict; 
use warnings; 
use Data::Dumper; 
use Data::Diver 'DiveRef'; 

my @array = ("tank", "tank/fs", "tank/fs/fs2a", "tank/fs/fs2b", "tank/fs/fs2c"); 
my %hash =(); 

foreach my $element (@array) { 
    DiveRef(\%hash, \(split /\//, $element)); 
} 

print Dumper \%hash; 

(код предоставляется ysth в this answer на другой вопрос.)

Update

Массив в коде это просто пример. Реальный массив имеет ~ 100 элементов, поэтому решение не может быть жестко закодировано.

+0

ли структура данных всегда будет HoHoA? – ikegami

ответ

1
DiveVal(\%data, 'tank', 'fs', 0) = 'fs2a'; 
DiveVal(\%data, 'tank', 'fs', 1) = 'fs2b'; 
DiveVal(\%data, 'tank', 'fs', 2) = 'fs2c'; 

или

push @{ DiveVal(\%data, 'tank', 'fs') }, 'fs2a'; 
push @{ DiveVal(\%data, 'tank', 'fs') }, 'fs2b'; 
push @{ DiveVal(\%data, 'tank', 'fs') }, 'fs2c'; 

Чтобы получить желаемую структуру данных из "tank", "tank/fs", "tank/fs/fs2a", "tank/fs/fs2b", "tank/fs/fs2c", необходима дополнительная информация. Например, вы могли бы понимать, что структура данных всегда будет HoHoA.

my @data = ("tank", "tank/fs", "tank/fs/fs2a", "tank/fs/fs2b", "tank/fs/fs2c"); 
my %data; 
for (@data) { 
    my @parts = split qr{/}; 
    if (@parts < 3) { 
     DiveVal(\%data, map \$_, @parts); 
    } else { 
     my $val = pop(@parts); 
     push @{ DiveVal(\%data, map \$_, @parts) }, $val; 
    } 
} 

Но какая такая ограниченная структура, нет оснований использовать Data :: Diver. Было бы гораздо быстрее избежать этого.

my @data = ("tank", "tank/fs", "tank/fs/fs2a", "tank/fs/fs2b", "tank/fs/fs2c"); 
my %data; 
for (@data) { 
    my @parts = split qr{/}; 
    if (@parts == 1) { \($data{$parts[0]}   ); } 
    elsif (@parts == 2) { \($data{$parts[0]}{$parts[1]}); } 
    else { push @{ $data{$parts[0]}{$parts[1]} }, $parts[2]; } 
} 

Вы могли бы даже быть в состоянии использовать

my @data = ("tank", "tank/fs", "tank/fs/fs2a", "tank/fs/fs2b", "tank/fs/fs2c"); 
my %data; 
for (@data) { 
    my @parts = split qr{/}; 
    push @{ $data{$parts[0]}{$parts[1]} }, $parts[2] if @parts == 3; 
} 
+0

Последнее потрясающе! Второе, последнее, дает мне «бесполезное использование push» и синтаксическую ошибку в строке 'if'. –

+1

Исправлены различные ошибки. Это последнее предполагает, что элементы с только одной или двумя частями являются излишними (т. Е. В конечном итоге последует одна с тремя частями). – ikegami