简体   繁体   中英

How can I create an anonymous hash from an existing hash in Perl?

How can I create an anonymous hash from an existing hash?

For arrays, I use:

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

but I can't find how to do the same for a hash:

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

Thanks

Why do you need an anonymous hash? Although the answers tell you various ways you could make an anonymous hash, we have no idea if any of them are the right solution for whatever you are trying to do.

If you want a distinct copy that you can modify without disturbing the original data, use dclone from Storable, which comes with Perl. It creates a deep copy of your data structure:

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

Consider Dave Webb's answer, but with an additional layer of references. The value for the key of c is another hash reference:

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) ] ),
    ;

By inspecting the output, you see that even though you have an anonymous hash, it's still linked to the original:

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
        };
my $new_hash = { %existing_hash };

Note that this solution does not make a deep copy. Read brian's answer for explanation.

I think you need to be careful here. Consider the following hash:

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

There are two ways you can get a reference from this:

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

$ref is a reference to the original hash and can be used similarly to %hash . $anon is a reference to an anonymous copy of the original hash; it will have the same data but changing it won't change the original hash and vice versa.

So, for example, to start with both of these statements will have the same output

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

But if I change the original hash:

$hash{1} = "i";

They two print statements would output different values:

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

If you have

my %hash = ...

then you can do

my $hashref = \%hash;

There seem to be two things going on here, and the answers are split between answering two different possible questions.

  1. You want an anonymous hash. Easy. You can do it in one step.
  2. You want an anonymous copy of an existing hash. As Dave Webb and brian suggest, this might be if you want a reference, but you don't want to tamper with the original hash. Also easy. (Well, not exactly: see brian's answer for details on deep copies.)

If you want 1, do this:

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

If you want 2, do this:

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

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

(The names are not meant for prime time.) My copy isn't ready for prime time either. See brian's post for a fuller, more precise discussion.

使用:

$hashref = {};

A quick/easy way to achieve a deep copy:

use FreezeThaw qw(freeze thaw);
$new = thaw freeze $old;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM