S3.Blog

30 Апреля 2017
A A A   RSS-лента
"Я знаю, что ничего не знаю, но многие не знают и этого". Сократ [?].

Perl: Как сделать дубликат анонимных переменных

Дата последнего изменения: 15 Октября 2009
Метки статьи: Готовые решения, © Авторское, Perl
Всякий, кто использует в программе анонимные хэши и массивы, не раз сталкивался с необходимостью создания автономного и независимого дубликата переменной. Вариантов решения много, в том числе и с помощью сериализации.
 

Если кому-то первый абзац показался непонятным, то сейчас разжую.
Допустим у вас есть переменная $a с такой структурой:
my $a = {
	name => 'Vasya',
	date => '2009-10-15',
};
И теперь вам надо создать дубликат этой переменной. Казалось бы что тут сложного:
my $b = $a;
А вот тут-то и заковыка: у нас $a это не просто переменная, а анонимный хэш массив, ссылку на который мы продублировали в переменную $b и теперь, если изменить значение в $b , то оно изменится и в $a
$b->{name} = 'Petya';

print $a->{name}; # Будет выведено Petya

Ага!, скажете вы и сделаете присвоение так:
my $b = {};
$b->{name} = $a->{name};
$b->{date} = $a->{date};
Или так:
my $b = {};
map {
	$b->{$_} = $a->{$_};
}keys %{$a};
Решение правильное, но оно годится для простых структур. А что если в $a у вас куча вложенных  хэшей и массивов? Тогда вам придётся написать метод, который рекурсивно вызывая сам себя, пройдется по всем закоулкам нашей переменной. Выглядеть он будет примерно так:
sub copy_var {
        my $var  = shift;
        my $out  = undef;

        if (ref($var) eq 'HASH') {
                foreach my $k (keys %{$var}) {
                        my $res = copy_var($var->{$k});
                        $out->{$k} = $res;
                }
        } elsif (ref($var) eq 'ARRAY') {
                foreach my $a (@{$var}){
                        my $res = copy_var($a);
                        push(@{$out}, $res);
                }
        } elsif (ref(\$var) eq 'SCALAR') {
                return $var;
        }

        return $out;
}
и копирование $a в $b будет происходить так:
$b = copy_var($a);
Но есть еще, как минимум два быстрых способа сделать копию переменной,- используя сериализацию.

Сериализация (в программировании) — процесс перевода какой-либо структуры данных в последовательность битов. Обратной к операции сериализации является операция десериализации — восстановление начального состояния структуры данных из битовой последовательности.

Сериализация используется для передачи объектов по сети и для сохранения их в файлы. Например, нужно создать распределённое приложение, разные части которого должны обмениваться данными со сложной структурой. В таком случае для типов данных, которые предполагается передавать, пишется код, который осуществляет сериализацию и десериализацию. Объект заполняется нужными данными, затем вызывается код сериализации, в результате получается, например, XML-документ. Результат сериализации передаётся принимающей стороне, например, по электронной почте или HTTP. Приложение-получатель создаёт объект того же типа и вызывает код десериализации, в результате получая объект с теми же данными, что были в объекте приложения-отправителя.


Вариант первый, используя класс Data::Dumper
use Data::Dumper;
my $r = Dumper($a);
eval "\$b = $r";
Вариант второй, используя класс Storable
use Storable qw(nfreeze thaw);
my $r = nfreeze($a);
my $b = thaw($r);

Как вы заметили, вся структура хранится в промежуточной переменной $r (в первом варианте в виде текста, во втором в виде двоичных данных), поэтому, в случае надобности, можно легко сохранить её в базе данных или в обычном файле, а потом, по необходимости, прочитать и обратно преобразовать в нормальную переменную (десериализировать).


Похожие материалы:




Junker (гость) • ответить
помойму проще вариант:
%bh = %$a;
$b = \%bh;
Александрответить
Вариант неверный! Тем более он неверен, если в хэше есть вложенные массивы.
В вашем случае изменяя хэш %bh или %$b автоматом будут изменены данные и в хэше %$a

 
 
  Имя *:   Решите пример *: =
 
Полужирный Курсив Подчеркнутый Перечеркнутый
 
Вставить изображение Сделать цитатой Вставить ссылку Вставить код

Вставить смайл
 
 

 



© S3.Blog: Если критикуешь, не предлагая решения проблемы, то ты становишься частью этой проблемы.