Как я могу создать анонимный хеш из существующего хеша в Perl? - PullRequest
5 голосов
/ 06 апреля 2009

Как я могу создать анонимный хеш из существующего хеша?

Для массивов я использую:

@x = (1, 2, 3);
my $y = [@x];

но я не могу найти, как сделать то же самое для хэша:

my %x = ();
my $y = ???;

Спасибо

Ответы [ 7 ]

15 голосов
/ 06 апреля 2009

Зачем вам нужен анонимный хеш? Хотя ответы говорят вам о различных способах создания анонимного хэша, мы не знаем, является ли какой-либо из них правильным решением для всего, что вы пытаетесь сделать.

Если вам нужна отдельная копия, которую можно изменить, не нарушая исходные данные, используйте dclone из Storable, который поставляется с Perl. Это создает глубокую копию вашей структуры данных:

use Storable qw(dclone);
my $clone = dclone \%hash;

Рассмотрим ответ Дейва Уэбба, но с дополнительным уровнем ссылок. Значение для ключа c является еще одной ссылкой на хэш:

use Data::Dumper;

my %original = ( a => 1, b => 2, c => { d => 1 } );
my $copy = { %original };

print 
    "Before change:\n\n",
    Data::Dumper->Dump( [ \%original], [ qw(*original) ] ),
    Data::Dumper->Dump( [ $copy ], [ qw(copy) ] ),
    ;

$copy->{c}{d} = 'foo';

print 
    "\n\nAfter change:\n\n",
    Data::Dumper->Dump( [ \%original], [ qw(*original) ] ),
    Data::Dumper->Dump( [ $copy ], [ qw(copy) ] ),
    ;

Изучив выходные данные, вы увидите, что, хотя у вас есть анонимный хэш, он все равно связан с оригиналом:

Before change:

%original = (
              'c' => {
                       'd' => 1
                     },
              'a' => 1,
              'b' => 2
            );
$copy = {
          'c' => {
                   'd' => 1
                 },
          'a' => 1,
          'b' => 2
        };


After change:

%original = (
              'c' => {
                       'd' => 'foo'
                     },
              'a' => 1,
              'b' => 2
            );
$copy = {
          'c' => {
                   'd' => 'foo'
                 },
          'a' => 1,
          'b' => 2
        };
13 голосов
/ 06 апреля 2009
my $new_hash = { %existing_hash };

Обратите внимание, что это решение не делает глубокую копию. Прочитайте ответ Брайана для объяснения.

8 голосов
/ 06 апреля 2009

Я думаю, вы должны быть осторожны здесь. Рассмотрим следующий хеш:

my %hash = (1 => 'one',2 => 'two');

Есть два способа получить ссылку из этого:

my $ref = \%hash;
my $anon = {%hash};

$ref является ссылкой на оригинальный хэш и может использоваться аналогично %hash. $anon - ссылка на анонимную копию оригинального хэша; он будет иметь те же данные, но его изменение не изменит исходный хеш и наоборот.

Так, например, для начала оба эти оператора будут иметь одинаковый вывод

print $ref->{1},"\n";
> one
print $anon->{1},"\n";
> one

Но если я изменю исходный хеш:

$hash{1} = "i";

Они из двух операторов print будут выводить разные значения:

print $ref->{1},"\n";
> i
print $anon->{1},"\n";
> one
2 голосов
/ 06 апреля 2009

Если у вас есть

my %hash = ...

тогда вы можете сделать

my $hashref = \%hash;
1 голос
/ 06 апреля 2009

Здесь, похоже, происходит две вещи, и ответы делятся между ответами на два возможных вопроса.

  1. Вы хотите анонимный хеш. Легко. Вы можете сделать это за один шаг.
  2. Вы хотите анонимную копию существующего хэша. Как предполагают Дейв Уэбб и Брайан, это может быть, если вам нужна ссылка, но вы не хотите подделать оригинальный хеш. Тоже легко. (Ну, не совсем: подробности см. В ответе Брайана.)

Если вы хотите 1, сделайте это:

my $hash_ref = { foo => 1, bar => 2 };

Если вы хотите 2, сделайте это:

my %hash = ( foo => 1, bar => 2 );

# Then later
my $anon_copy_hash_ref = { %hash };

(Имена не предназначены для прайм-тайма.) Моя копия также не готова к прайм-тайм. См. Сообщение Брайана для более полного и точного обсуждения.

0 голосов
/ 06 апреля 2009

Быстрый / простой способ получить глубокую копию:

use FreezeThaw qw(freeze thaw);
$new = thaw freeze $old;
0 голосов
/ 06 апреля 2009

Использование:

$hashref = {};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...