简体   繁体   English

在Perl中解引用数组键

[英]Dereferencing an array key in Perl

Consider this Perl script: 考虑以下Perl脚本:

use strict;

my %new;
my $test_ref = [24, 26, 55];
$new{$test_ref} = 10;

foreach my $key (keys %new){
    print $key->[0];
}

When I try to access this element, it gives an error like: 当我尝试访问此元素时,它给出了如下错误:

Can't use string ("ARRAY(0x...)") as an ARRAY ref 不能使用字符串(“ ARRAY(0x ...)”)作为数组引用

Why? 为什么?

Because a hash key is always stringified, and a stringified value of an array REFERENCE (which $test_ref is) is exactly that: "ARRAY(0x...)" . 因为哈希键始终是字符串化的,并且数组REFERENCE( $test_ref是)的字符串化值恰好是: "ARRAY(0x...)" This is different from Java maps which can store arbitrary object as a key. 这与Java映射不同,后者可以将任意对象存储为键。

Therfore, your hash would have 1 ket-value pair, with the key being a string " "ARRAY(0x...)" " 因此,您的哈希将具有1个ket-value对,其密钥为字符串“ "ARRAY(0x...)"

So, when you have your for loop, it loops over all the keys (all 1 of them), and then assigns the key value (a string "ARRAY(0x...)" ) to $key variable. 因此,当您有for循环时,它将循环所有键(全部1个键),然后将键值(字符串"ARRAY(0x...)" )分配给$key变量。

You then try to array-dereference that string - which of course can't be done since it is not an array reference - it is merely a string containing the string representation of what array reference used to be. 然后,您尝试对该字符串进行数组解引用-因为它不是数组引用 ,所以当然不能这样做-它只是一个字符串,其中包含以前使用的数组引用的字符串表示形式。

If you want to have "24, 26, 55" as 3 hash keys, you can do this: 如果要将“ 24、26、55”作为3个哈希键,则可以执行以下操作:

my %new = map { $_ => 10 } @$test_ref;

If you actually want to store a list in a hash key, it's doable but not always (in your case of a list of integers, you can, but it's slow, clumzy and I can't imagine when you'd ever wish to. 如果您确实想将列表存储在哈希键中,那么它是可行的,但并非总是如此(在整数列表的情况下,您可以,但是它很慢,笨拙,我无法想象您何时会希望这么做。

# Trivial example:
my $test_ref = [24, 26, 55];
$new{ join(",",@$test_ref) } = 10;
foreach my $key (keys %new){
    my @list = split(/,/,$key);
    print $list[0];
}

This approach has some performance penalties, and can be optimized a bit (eg by memoizing the split results). 这种方法会有一些性能损失,并且可以进行一些优化(例如,通过记录拆分结果)。 But again, for pretty much ANY reason you might want to do this, there probably are better solutions. 但是,出于几乎任何原因,您可能都想这样做,但也许还有更好的解决方案。

Hash keys are normally stringified, so they lose the ability to act as a reference. 哈希键通常是字符串化的,因此它们失去了充当引用的功能。

The core module Tie::RefHash provides this capability: 核心模块Tie :: RefHash提供了以下功能:

use strict;
use warnings;
use Tie::RefHash;

tie my %new, 'Tie::RefHash';
my $test_ref = [24, 26, 55];
$new{$test_ref} = 10;

foreach my $key (keys %new){
    print $key->[0];
}

Good job using strict. 严把好用。 But warnings is even more important. 但是警告更为重要。

I'm guessing (and I may be wrong) that you want to assign 24, 26 and 55 as the keys of %new . 我猜(您可能错了),您想将24、26和55分配为%new的键。

If you want to do this, the following is what you're after: 如果要执行此操作,请遵循以下内容:

use strict;

my %new;
my $test_ref = [24, 26, 55];

@new{@$test_ref} = (10) x @$test_ref;

print "$new{$_}\n" foreach keys %new;

If you want to access the array reference $test_ref , then you want to use the array syntax (square brackets) 如果要访问数组引用$test_ref$test_ref使用数组语法(方括号)

$test_ref->[0];

If you want to access the hash %new , then use the hash syntax (braces) 如果要访问哈希%new ,请使用哈希语法(大括号)

$new{$key}

What you are doing is using an array reference $test_ref as a key into a hash %new - what perl does is convert that array reference into a string to use at the key. 您正在做的是使用数组引用$test_ref作为哈希%new的键$test_ref所做的是将数组引用转换为字符串以供键使用。 It is the string and not the reference that is returned by keys . keys返回的是字符串而不是引用。

You can't use references as keys and then get the reference back again (trivially). 您不能将引用用作键,然后再次(简单地)重新获得引用。

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

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