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


Автор: bonger 27.4.2011, 13:24
Приветствую всех, вопрос следующий.
Допустим есть сложная структура данных. Типа массив ссылок на хеши в которых ссылки на массивы в которых ссылки на другие массивы, хеши, скаляры и.т.п.
И есть ссылка на один из элементов.
Могу ли я по ней получить путь к этому элементу в общей структуре.
Для примера:
@arr = [{key0 => [{key1 => [["tryToFind"],[15]]},{key2=>[20]}]}] - адская структура.
Мы разбирали структуру и сохранили ссылку на что то. Нарпимер $link.
ref($link); #SCALAR
print $$link; #15
Нам нужно по этим данным получить полный путь к элементу в структуре, типа такого:
@arr[0]->[0]{key0}[0]->{key1}[1][0]; #путь к тем же "15".
Нет ли каких модулей, позволяющих это сделать легко и непринужденно?

Автор: arto 27.4.2011, 14:04
perldoc Data::Traverse

только как вы одни 15 будете отличать от других?

Автор: bonger 27.4.2011, 14:13
Так.. как бы образно говоря ссылка - ссылается на область памяти. А когда мы получаем доступ к элементу любым другим способом - мы точно так же обращаемся к этой же области памяти. Как можно их спутать?
По поводу Traverse сейчас посмотримс, спасибо.

Tracerse не совсем то... Хотелось бы типа(в продолжение предыдущего кода):

print magic_data_finder(@arr, $link); # вывел бы нам @arr[0]->[0]{key0}[0]->{key1}[1][0]

Автор: mishnik 29.4.2011, 15:31
Цитата(bonger @  27.4.2011,  13:24 Найти цитируемый пост)
@arr = [{key0 => [{key1 => [["tryToFind"],[15]]},{key2=>[20]}]}] - адская структура.

очень плохой код, для данных сущетсвют базы данных!!!
что за задача то?

Автор: Pfailed 27.5.2011, 21:17
Просто написать рекурсивную функцию
Код

use strict;
use Data::Dumper;

my $link = [15];
my $arr = [{key0 => [{key1 => [["tryToFind"],$link]},{key2=>[20]}]}];

if (my $found = find($arr, $link, '$arr')) {
    print $found, ":\n", Dumper(eval "$found");
}
else {
    print "Not found\n";
}

sub find($$$) {
    my ($arg, $link, $res) = @_;
    my $ref = ref $arg;
    
    if ($link == $arg) {
        return $res;
    }
    elsif ($ref eq 'ARRAY') {
        for (my $i=0; $i<@$arg; $i++) {
            if (my $rv = find($arg->[$i], $link, $res."->[$i]")) {
                return $rv;
            }
        }
    }
    elsif ($ref eq 'HASH') {
        while (my ($k, $v) = each %$arg) {
            if (my $rv = find($v, $link, $res."->{$k}")) {
                return $rv;
            }
        }
    }
    elsif ($ref) {
        die 'Not supported reference type: ', $ref;
    }
    
    return undef;
}


Цитата

$arr->[0]->{key0}->[0]->{key1}->[1]:
$VAR1 = [
          15
        ];


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