简体   繁体   English

如何从Perl中的现有哈希创建匿名哈希?

[英]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. 如果您想要一个可以在不打扰原始数据的情况下修改的独特副本,请使用Perl附带的Storable中的dclone 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: 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) ] ),
    ;

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. 阅读brian的答案进行解释。

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 . $ref是对原始哈希的引用,可以类似于%hash $anon is a reference to an anonymous copy of the original hash; $anon是对原始哈希的匿名副本的引用; 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语句将输出不同的值:

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. 正如Dave Webb和brian建议的那样,如果你想要一个引用,可能就是这样 ,但是你不想篡改原始哈希。 Also easy. 也很容易。 (Well, not exactly: see brian's answer for details on deep copies.) (嗯,不完全是这样的:看看brian关于深拷贝细节的答案。)

If you want 1, do this: 如果你想要1,请执行以下操作:

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

If you want 2, do this: 如果你想要2,请执行以下操作:

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. 请参阅brian的帖子,以获得更全面,更精确的讨论。

使用:

$hashref = {};

A quick/easy way to achieve a deep copy: 快速/简单的方法来实现深层复制:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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