Как я могу выполнить данную функцию для каждого элемента сложной структуры данных в Perl? - PullRequest
1 голос
/ 17 декабря 2008

Я хочу декодировать все объекты HTML в сложной структуре данных. В основном я ищу функцию "super map ()". Вот что у меня есть:

sub _html_decode {
    my $self = shift;
    my $ref = shift;

    if (ref($ref) eq "HASH") {
        $self->_html_decode_hash($ref)
    }
    if (ref($ref) eq "ARRAY") {
        $self->_html_decode_array($ref);
    }

}

sub _html_decode_array {
    my $self = shift;
    my $ref = shift;

    unless (@$ref) {return;}

    foreach (0 .. (scalar(@$ref) - 1)) {
        if (ref($ref->[$_]) eq "HASH") {
            $self->_html_decode_hash($ref->[$_]);
        }
        if (ref($ref->[$_]) eq "ARRAY") {
            $self->_html_decode_array($ref->[$_]);
        }
        else {
            $ref->[$_] = decode_entities($ref->[$_]);
        }
    }
}

sub _html_decode_hash {
    my $self = shift;
    my $ref = shift;

    unless (%$ref) {return;}

    while (my ($k, $v) = each %$ref) {
        if (ref($v) eq "HASH") {
            $self->_html_decode_hash($v);
        }
        if (ref($v) eq "ARRAY") {
            $self->_html_decode_array($v)
        }
        else {
            $ref->{$k} = decode_entities($v);
        }
    }
}

Ответы [ 3 ]

3 голосов
/ 17 декабря 2008

Чтобы выполнить подпрограмму для каждого элемента произвольной сложной структуры данных, ознакомьтесь с шаблоном проектирования Visitor. По сути, ваша структура данных - это объект, который знает, какие элементы ему еще нужно обработать, и применяет к ним вашу подпрограмму. Там также есть немного паттерна Iterator, потому что вы понимаете, как

У меня есть пример в моем модуле Netscape :: Bookmarks . Эта структура данных глубоко вложена в несколько различных типов объектов. При использовании шаблона Visitor большая часть сложности ушла.

Кроме того, вы можете проверить мой модуль Object :: Iterate . Он имеет функцию imap, которая работает с объектами вместо списков. Я украл идею __next__ из Python и применил ее к Perl.

3 голосов
/ 17 декабря 2008

Я думаю, что так и должно быть, но я не проверял.

sub _html_decode {
    my ($self, $ref) = @_;

    if (ref($ref) eq "HASH") {
        for my $value (values %{$ref}) {
            $self->_html_decode($value);
        }
    }
    elsif (ref($ref) eq "ARRAY") {
        for my $value (@{$ref}) {
            $self->_html_decode($value);
        }
    }
    else {
        $_[1] = decode_entities($_[1]);
    }
}

Я признаю, что последняя часть не очень симпатична.

2 голосов
/ 18 декабря 2008

Data :: Rmap , кажется, делает это также. У кого-нибудь есть опыт работы с этим модулем?

...