Копирование hashref в Perl
Возможный дубликат:
Каков наилучший способ сделать глубокую копию структуры данных в Perl?
Я, по-видимому, неправильно понимаю что-то о том, как hashrefs работают в Perl, и я здесь, чтобы исправить это.
Мне нужно получить копию hashref, с которой я могу играть без изменения оригинала. Согласно мои исследования, копирование hashref так же просто, как использование оператора equals:
my $hashref_copy = $hashref;
Но насколько я могу судить, все, что делает, это сделать $hashref_copy
указателем на исходный объект. Рассмотрим этот бит игры:
my $hashref = {data => "fish"};
my $hashref_copy = $hashref;
$hashref_copy->{data} = "chips";
print "$hashref->{data}\n";
Если $hashref_copy
действительно была независимой копией, я бы ожидал, что этот код напечатает "рыбу". Вместо этого он печатает "чипы".
Итак, либо 1) я что-то недопонимаю или 2) Perl нарушен. Я совершенно уверен, что это не № 2, несмотря на то, что мое эго могло бы подумать.
Где я ошибаюсь? И что мне нужно сделать, чтобы внести изменения в $hashref_copy
not в исходном $hashref
?
Ответы
Ответ 1
Когда вы копируете hashref в другой скаляр, вы копируете ссылку на тот же хеш. Это похоже на копирование одного указателя в другой, но не изменение какой-либо заостренной памяти.
Вы можете легко создать мелкую копию хэша:
my $copy = { %$source };
Бит %$source
в контексте списка будет расширяться до списка пар значений ключа. Кудрявые фигурные скобки (анонимный хэш-конструктор) затем берут этот список, а создает из него новый hashref. Неглубокая копия прекрасна, если ваша структура 1-мерная, или если вам не нужно клонировать любую содержащуюся структуру данных.
Чтобы сделать полную глубокую копию, вы можете использовать основной модуль Storable
.
use Storable 'dclone';
my $deep_copy = dclone $source;
Ответ 2
Да, назначение просто копирует ссылку (например, копирование значения указателя на другие языки). То, что вы ищете, называется "глубокой копией".
Storable::dclone
представляется одним из решений (perldoc Storable
для получения дополнительной информации).
Ответ 3
Если это просто хэш и все, что вы ищете, это его копия:
my $hashref = {data => "a"};
my %hash_copy = %{$hashref}; # Create a copy of the hash that $hashref points to
my $hashref_copy = \%hash_copy; # Ref to %hash_copy
$hashref_copy->{data} = "b";
print "$hashref->{data}\n"; # Outputs 'a'
print "$hashref_copy->{data}\n"; # Outputs 'b'