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

Сделайте весь шаблон класса athing другом:

template<int J> class bthing {
    // ...
    template<int I> friend class athing;
};

staticxfer не обязательно быть другом, поскольку он может повторно использовать athing::transfer.

template<int J> friend void staticxfer(athing &a, const bthing<J> &b) {
    a.transfer(b);
}
5
задан brian d foy 6 April 2009 в 13:15
поделиться

7 ответов

my $new_hash = { %existing_hash };

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

13
ответ дан 18 December 2019 в 05:21
поделиться

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

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
8
ответ дан 18 December 2019 в 05:21
поделиться

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

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

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

Рассмотрите ответ Dave Webb, но с дополнительным слоем ссылок. Значение для ключа 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
        };
15
ответ дан 18 December 2019 в 05:21
поделиться

Если Вы имеете

my %hash = ...

затем можно сделать

my $hashref = \%hash;
2
ответ дан 18 December 2019 в 05:21
поделиться

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

$hashref = {};
0
ответ дан 18 December 2019 в 05:21
поделиться

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

  1. Вы хотите анонимный хеш. Легкий. Можно сделать это за один шаг.
  2. Вы хотите анонимную копию существующего хеша. Как Dave Webb и brian предполагают, это могло бы быть то, если Вы хотите ссылку, но Вы не хотите вмешиваться в исходный хеш. Также легкий. (Ну, не точно: см. ответ brian для получения дополнительной информации о глубоких копиях.)

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

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

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

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

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

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

1
ответ дан 18 December 2019 в 05:21
поделиться

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

use FreezeThaw qw(freeze thaw);
$new = thaw freeze $old;
0
ответ дан 18 December 2019 в 05:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: