关于以下代码的两个问题:
%h1 = {
'key1' => ( 1, 2, 3 ),
'key2' => ( 4, 5, 6 )
};
%h2 = {
'key1' => [ 1, 2, 3 ],
'key2' => [ 4, 5, 6 ]
};
print $(@h1{'key2'})[1];
Run Code Online (Sandbox Code Playgroud)
Q1:h1和h2有什么区别?请不要说'一个是列表的哈希和另一个数组的哈希'...相反,我想知道在使用方面的转换.
Q2:为什么$(@h1{'key2'})[1]print语句中的引用不能编译?这是我的想法:我想访问对应于'key2'的数组/列表:@h1{'key2'}.然后我想访问该列表/数组中索引1处的标量:$(@h1{'key2'})[1].为什么这是错的?这个变量引用的东西很混乱.
Oes*_*sor 14
这些都不像你想的那样工作.使用严格并始终使用警告.
%h1 = {
'key1' => ( 1, 2, 3 ),
'key2' => ( 4, 5, 6 )
};
Run Code Online (Sandbox Code Playgroud)
您正在尝试将hashref({}构造)分配给哈希.它被字符串化为标量,并在%h1中用作键,值为undef.另外,因为你正在使用列表(()构造),它会变得扁平,你正在创建哈希:
%href = ( key1 => 1,
2 => 3,
key2 => 4,
5 => 6,
);
Run Code Online (Sandbox Code Playgroud)
在后一种情况下,您使用数组引用([]构造)正确创建哈希,但您仍然在为哈希分配href.你想做:
%h1 = (
'key1' => [ 1, 2, 3 ],
'key2' => [ 4, 5, 6 ]
);
Run Code Online (Sandbox Code Playgroud)
这将通过引用在列表上下文中创建%h1,在标量上下文中创建值.
区别:他们都错了!:)
列表是扁平结构; 你不能有列表列表,你只需要一个(一维)列表.
参考文献是标量.所以%h1 = { ... }没有意义.你正在做的只是分配一个单元素列表%h1,它被字符串化并变成一个键.这相当于
%h1 = ( 'HASH(0x1fb872a0)' => undef );
Run Code Online (Sandbox Code Playgroud)
其中键是保存该哈希引用的任何内存地址的字符串化版本.
要创建数组哈希,请执行以下操作:
my %h1 = ( key1 => [ 1, 2, 3 ], key2 => [ 4, 5, 6 ] );
Run Code Online (Sandbox Code Playgroud)
如果要引用数组哈希,可以使用:
my $ref = { key1 => [ 1, 2, 3 ], key2 => [ 4, 5, 6 ] };
Run Code Online (Sandbox Code Playgroud)
要么
my $ref = \%h1;
Run Code Online (Sandbox Code Playgroud)
最后,要访问您的结构元素,您可以使用:
print $h1{key2}[1];
Run Code Online (Sandbox Code Playgroud)
要么
print $ref->{key2}[1];
Run Code Online (Sandbox Code Playgroud)
在后一种情况下,我们使用->运算符来取消引用结构.对于后续级别,->假设,但您也可以写
print $ref->{key2}->[1];
Run Code Online (Sandbox Code Playgroud)
如果你发现更清楚.
要从引用中获取完整的结构(例如使用keys),您需要使用另一种形式的解除引用:
my @keys = keys %$ref; # or more explicitly %{ $ref }
Run Code Online (Sandbox Code Playgroud)
为了获得完整的内部结构,它是一样的:
my @a2 = @{ $ref->{key2} };
Run Code Online (Sandbox Code Playgroud)
以下优秀的Perl文档详细介绍了所有这些内容:
和别的.
不同之处在于%h1赋值完全错误,%h2赋值几乎正确.
Perl使用括号创建一个列表,可以将其分配给数组或哈希:
@a = (1, 2, 3);
%a = (foo => 'bar', 7 => 3);
Run Code Online (Sandbox Code Playgroud)
Perl使用括号创建列表引用,可以将其分配给标量.
$a = [ 1, 2, 3 ];
Run Code Online (Sandbox Code Playgroud)
Perl使用大括号来创建哈希引用,可以将其分配给标量.
$a = { key1 => 1, key2 => 2 };
Run Code Online (Sandbox Code Playgroud)
要记住的另一个重点是哈希表的值总是标量.在Perl中没有"哈希哈希"的"哈希列表" - 这些是方便的术语,实际上意味着" 列表引用的哈希 "和" 哈希引用的哈希 ".
考虑到这一点,让我们看看你的例子:
%h1 = { ... };
Run Code Online (Sandbox Code Playgroud)
已经错了.大括号创建一个哈希引用,它被视为单个标量,你正在做的是等价于:
$scalar = { ... };
%h1 = ( "$scalar" => undef );
Run Code Online (Sandbox Code Playgroud)
所以%h1包含一个简单的名称,HASH(0x54321098)而不是你的意思.相反,说
%h1 = ( ... )
Run Code Online (Sandbox Code Playgroud)
继续,
%h1 = (
'key1' => ( 1, 2, 3 ),
'key2' => ( 4, 5, 6 )
);
Run Code Online (Sandbox Code Playgroud)
也不会做你想做的事情.在这个赋值中有列表,而不是列表引用,另外要记住的是Perl"扁平化"列表.如果你认为=>它是逗号的同义词(这几乎是真的),那么你会看到这个赋值相当于:
%h1 = ( 'key1', 1, 2, 3, 'key2', 4, 5, 6 );
Run Code Online (Sandbox Code Playgroud)
要么
%h1 = ( 'key1' => 1,
2 => 3,
'key2' => 4,
5 => 6 );
Run Code Online (Sandbox Code Playgroud)
创建一个包含四个键值对的哈希表,而不是您期望的两个键值对.
如果我们修复了%h2作业周围的大括号,那么
%h2 = ( key1 => [ 1, 2, 3 ],
key2 => [ 4, 5, 6 ] );
Run Code Online (Sandbox Code Playgroud)
会做你期望的.请记住,哈希表的值必须是标量,列表引用是标量.然后,您可以说出类似于$h2{'key1'}[1]列表元素的内容(在本例中为2).