2013-10-28 2 views
6

У меня есть структура, которая выглядит следующим образом (хэш хэш):Perl Grep вложенных хэш рекурсивного

%hash=(
Level1_1=> {  
Level2_1 => "val1", 
Level2_2=> { 
    Level3_1 => "val2", 
    Level3_2 => "val1", 
    Level3_3 => "val3", 
}, 
Level2_3 => "val3", 
}, 
Level1_2=> { 
    Level2_1 => "val1", 
    Level2_2=> { 
    Level3_1 => "val1", 
    Level3_2 => "val2", 
    Level3_3 => "val3", 
    }, 
Level2_3 => "val3", 
}, 
Level1_3=> { 
    Level2_1 => "val1", 
    Level2_2 => "val2", 
    Level2_3 => "val3", 
}); 

Я хотел бы Grep эту вложенную структуру, отфильтрованную «val2» И вывод должен быть:

%result=(
    Level1_1=> { Level2_2=> { Level3_1 => "val2"} }, 
    Level1_2=> { Level2_2=> { Level3_2 => "val2" } }, 
    Level1_3=> { Level2_2 => "val2" } 
    ); 

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

hashwalk_v(\%hash); 
sub hashwalk_v 
{ 
    my ($element, @array) = @_; 
    if(ref($element) =~ /HASH/) 
    { 
    while (my ($key, $value) = each %$element) 
    { 

    if(ref($value) =~ /HASH/) { 
     push (@array, $key); 
     hashwalk_v($value, @array); 
    } else { 
     if ($value =~ "val2") { 
     push (@array, $key); 
     print $_ . "\n" for @array; 
     } else { 
     @array =""; 
     } 
    } 
    } 
} 
} 

но к сожалению, я не могу сохранить хэш-ключ из предыдущего цикла. Любые идеи?

ответ

6

Подобный подход,

use Data::Dumper; print Dumper hfilter(\%hash, "val2"); 

sub hfilter { 
    my ($h, $find) = @_; 
    return if ref $h ne "HASH"; 

    my %ret = map { 
    my $v = $h->{$_}; 
    my $new = ref($v) && hfilter($v, $find); 

    $new ? ($_ => $new) 
     : $v eq $find ? ($_ => $v) 
     :(); 

    } keys %$h; 

    return %ret ? \%ret :(); 
} 
+0

работаю также мелкий mpapec, спасибо! – ovntatar

5

Рекурсия - правильный ответ, но вы, похоже, немного путались по пути. :) Создайте новый хэш, как вы идете, один уровень, в то время:

sub deep_hash_grep { 
    my ($hash, $needle) = @_; 

    my $ret = {}; 
    while (my ($key, $value) = each %{$hash}) { 
     if (ref $value eq 'HASH') { 
      my $subgrep = deep_hash_grep($value, $needle); 
      if (%{$subgrep}) { 
       $ret->{$key} = $subgrep; 
      } 
     } 
     elsif ($value =~ $needle) { 
      $ret->{$key} = $value; 
     } 
    } 

    return $ret; 
} 
+0

Отлично, это то, что мне нужно Eevee, спасибо! – ovntatar

Смежные вопросы