我如何创建如下的哈希:
my %hash = (key1=>"Something", key2=>$hash{key1} . "Else");
当我声明哈希时,这不能完成吗?到目前为止,我唯一想到的是:
my %hash = (key1=>"Something");
$hash{key2} = $hash{key1} . "Else";
答案 0 :(得分:11)
为什么不使用中间变量?
my $common_value = 'Something';
my %some_hash = ( k1 => $common_value, k2 => $common_value.'Else' );
<强>更新强>
kemp问我们为什么需要一个中间变量。我可以用两种方式解释这个问题,我会努力回答这两种解释。
为什么不能my %hash = ( k1 => 'foo', k2 => $hash{k1}.'bar' );
?
在左侧(lhs)之前评估表达式的右侧(rhs)。因此,当确定k2
的值时,尚未对%hash
进行任何分配。事实上,%hash
甚至尚未创建并进入暂存区。 (%hash
这里是一个词法变量,所以它不会进入符号表。)
为什么要使用变量而不是其他方法?
嗯,有很多方法可以用这样的值初始化哈希。如果我有少量相关的键进行初始化,我会使用一个中间变量。
my $cv1 = sub_result() * 5;
my $cv2 = "Number: $cv1";
my %h = (
k1 => $cv1,
k2 => $cv2,
k3 => "Numero: $cv1",
k4 => "Big $cv2",
k5 => "Round $cv2",
k6 => "Whole $cv2",
k7 => "-$cv1",
);
但是,如果我必须构建许多依赖于许多不同键的复杂值,我可能会使用数据驱动方法来初始化哈希。确切的实现将取决于我没有的细节,但它可能看起来像这样:
use Scalar::Util qw(reftype);
my @init = (
[ key1 => $value ],
[ key2 => \&make_a_value, 'key1' ],
[ key3 => \&another_way, 'key2' ],
);
my %h;
for my $spec ( @init ) {
my $key = shift @$spec;
my $value = shift @$spec;
my @args = @$spec;
if( reftype $value eq reftype sub {} ) {
$value = $value->( @h{ @args } );
}
$h{$key} = $value;
}
对于此问题所针对的任何情况,选择使用何种技术取决于该实例特有的许多细节。因此,我们必须做出通用陈述。中间变量是解决OP问题的一种好方法。是否应该在他的特定情况下使用它,我不能说。
答案 1 :(得分:9)
由于两个原因无法完成:
在Perl处理key2 => $hash{key1}
时,它还没有将使用密钥1分配的内存与散列名称哈希相关联。换句话说,$hash{key1}
在指定key2 => $hash{key1}
之后才会指向内存中的正确位置。
之前的原因没有说明其他问题:在您处理%hash
时,您还没有将key2 => $hash{key1}
放入符号表中(再次解析/评估的顺序) ,所以编译器会像你一样use strict;
进行barf。在前面的陈述中声明my %hash
很容易解决这个问题,但#1不是。
答案 2 :(得分:4)
在您定义哈希的位置,$ hash {key1}不存在,因此您无法在一个语句中执行此操作。 您可以自己创建解决方案,并在定义密钥后使用密钥1。
答案 3 :(得分:1)
有什么问题
my %hash = ( key1 => "Something", key2 => "Something" . "Else" );
是的,我知道这些是占位符,但无论它们是什么,你在构建哈希时都知道它们(或者你根本不会构建它),那你为什么不加入它们呢? / p>
答案 4 :(得分:0)
首先,我会用中间值来做这件事。但是,您有两个单独的更高级选项。如果你是perl的新手,我不建议/其中任何一个 - 实际上我更喜欢中间价值解决方案,但是为了完整性:
->{key1}
)来访问对象,您可以使用perldoc perltie
找到有关此方法的更多信息,以及上面链接到Tie::Hash
; 这是一个Moose的例子。
package Class;
use Moose;
has [qw/key1 key2/] => ( isa => 'Str', is => 'rw', init_arg => 'key1' );
my $o = Class->new( { key1 => 'foobar' } );
print $o->key1, $o->key2;
答案 5 :(得分:0)
你可以相当接近,但我不确定它是否具有新颖性以外的价值:
$_->{key2} = $_->{key1} . "Else" for my $hash = { key1 => "Something" };
答案 6 :(得分:0)
如果在%hash中创建 之外的中间变量,那么使用do block
可能会让它更美观:
my %hash = (
do {
my $s = 'Something';
( key1 => $s, key2 => $s . 'Else' );
},
);
/ I3az /