Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Рекурсивный поиск в хешах и масивах


Автор: Logo 4.4.2012, 15:30
Есть ли модуль для рекурсивного поиска в хешах и массивах? То есть, допустим что бы сделать grep фильтр
Код

$data = {
   one => [
       'target'
   ],
   two => {
     foo => target
  },
  three => 'target',
  four => {foo => bar}
};

for (keys %$data) {
  dump $data->{$_} if Search($data->{$_}, qr/target/);
  #дамп one, two, three
}


Так же, хотелось бы, что бы умел находить путь к целевому элементу, например так:
Код

$data = {
  foo1 => {
    bar => { baz => 10 },
    foo2 => [
      { foo3 => 'target' },
      'baz',
    ],
    baz => [1, 2, 3],
  }
}

$path = Find($data, qr/target/);
dump $path;
#out:
#$VAR1 = {
#  foo1 => {
#    foo2 => [
#      { foo3 => 'target'}
#    ]
#  }
#}

#Либо так
print $path;
#out:
#$VAR1->{foo1}{foo2}[0]{foo3}

Автор: EcSYZ 4.4.2012, 18:06
Код

#!/usr/bin/perl
$|++;
use common::sense;
use Data::Dumper;


my $data = {
   'one' => [
       'target'
   ],
   'two' => {
     'foo' => 'target'
  },
  'three' => 'target',
  'four'  => {'foo' => 'bar'}
};

&search($data, 'target', 'root');

sub search
{
    my ($data, $template, $prefix) = @_;
    
    my $path = '';
    if(ref $data eq 'HASH'){
        foreach my $key(keys %$data){
            
            if(ref $data->{$key} eq 'HASH' || ref $data->{$key} eq 'ARRAY'){
                $path = search($data->{$key}, $template, $prefix.'->{'.$key.'}');
            } else {
                if($data->{$key} eq $template){
                    $path = $prefix.'->{'.$key.'}';
                }
            }
            if($path ne ''){ say "$path"; $path='';}
        }
    }
    if(ref $data eq 'ARRAY'){
        for(my $i=0; $i < scalar @$data; $i++){
            
            if(ref $data->[$i] eq 'HASH' || ref $data->[$i] eq 'ARRAY'){
                $path = search($data->[$i], $template, $prefix.'->['.$i.']');
            } else {
                if($data->[$i] eq $template){
                    $path   = $prefix.'->['.$i.']';
                }
            }
            if($path ne ''){ say "$path"; $path='';}
        }
    }
    return $path;
}



Код

[ecsyz@localhost trash_scripts]$ ./struct_search.pl 
root->{three}
root->{one}->[0]
root->{two}->{foo}

Автор: Pfailed 4.4.2012, 18:42
http://forum.vingrad.ru/topic-328094.html

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)