Perl 使用另一个哈希值定义哈希值。
当只使用一个数据结构时,是否有方法执行以下操作Perl 使用另一个哈希值定义哈希值。,perl,perl-data-structures,Perl,Perl Data Structures,当只使用一个数据结构时,是否有方法执行以下操作 my %hash = ( "key1" => "value1", "key2" => "value2", "key3" => $hash{key1}, ); 基本上,我想把散列的键值设置为另一个键值。我尝试了上述语法,但得到以下警告: Global symbol "%hash" requires explicit package name at ... 我假设这是因为我试图在实际创建哈希之前引用它。这是因为,在使用
my %hash = (
"key1" => "value1",
"key2" => "value2",
"key3" => $hash{key1},
);
基本上,我想把散列的键值设置为另一个键值。我尝试了上述语法,但得到以下警告:
Global symbol "%hash" requires explicit package name at ...
我假设这是因为我试图在实际创建哈希之前引用它。这是因为,在使用
$hash{key1}
时,符号“hash”尚未添加到符号表中。您的包还不知道什么是%hash
,因为在解析结束“)”之前,它不会被添加到符号表中,但它会在前面遇到符号1行
您需要提前声明%hash:
my %hash;
%hash = (
"key1" => "value1",
"key2" => "value2",
"key3" => $hash{key1},
);
然而,尽管上面的代码将被编译,它将不会像预期的那样工作,因为在计算$hash{key1}
时,还没有为%hash
分配任何内容。您需要首先将其作为单独的语句进行分配:
my %hash;
%hash = (
"key1" => "value1",
"key2" => "value2",
);
%hash = %hash, (
"key3" => $hash{key1},
); # Or simply $hash{key3} = $hash{key1};
请注意,上述仅将值从
key1
复制到key3
,一次。在那之后,它们就没有任何联系/关联。如果要将key1
和key3
别名(例如,使它们指向相同的值,而不是包含该值的副本),这是可能的,但也不是那么简单。您需要将其转换为绑定哈希并编写定制的绑定处理程序以使其正确,或者使每个键的值都是一个引用如果您希望$hash{key1}成为$hash{key3}的别名,那么可以使用简单的方法来实现
$hash{key1}和$hash{key3}现在将引用单个值,对其中一个值的更新将在另一个值中可见。您可以使用核心模块
hash::Util
访问低级hv_store
例程,该例程可以将哈希值别名在一起。它看起来不像使用Data::Alias
那样干净,但它已经安装好了
use Hash::Util 'hv_store';
my %hash = (
key1 => "value1",
key2 => "value2",
);
hv_store %hash, key3 => $hash{key1};
say "$_: $hash{$_}" for sort keys %hash;
# key1: value1
# key2: value2
# key3: value1
$hash{key1} = 'new value';
say "$_: $hash{$_}" for sort keys %hash;
# key1: new value
# key2: value2
# key3: new value
如果不希望别名持续到初始赋值之后,则可以只写一行:
$hash{key3} = $hash{key1}
在初始声明之后,使用
hv_store
%hash创建要分配给散列的值列表时不包含任何内容,因为您尚未将列表分配给散列
事实上,在创建要分配给哈希的值列表时,%hash
不存在,因为分配在计算其LHS之前先计算其RHS。这就是为什么你会得到一个严格的错误
您可能喜欢的一些解决方案:
my %hash = (
key1 => "value1",
key2 => "value2",
key3 => "value1",
);
my $value1 = "value1";
my %hash = (
key1 => $value1,
key2 => "value2",
key3 => $value1,
);
my %hash = (
( map { $_ => "value1" } qw( key1 key3 ) ),
key2 => "value2",
);
你可以说
my %h;
my $i = 0;
while (
my ( $k, $v ) = (
key1 => '"value1"',
key2 => '"value2"',
key3 => '$h{key1}',
)[ $i, $i + 1 ]
)
{
$h{$k} = eval $v;
$i += 2;
}
只要引用的任何键在引用之前出现在列表中。为什么不创建自己的功能:
use strict;
use warnings;
sub make_hash (@) {
my %h;
my @unresolved;
while ( @_ ) {
my ( $key, $value ) = splice( @_, 0, 2 );
next unless defined $value;
if ( not ref( $value )
and my ( $ref ) = $value =~ /^ref:\s*(.*\S)\s*$/
) {
if ( defined( my $v = $h{ $ref } )) {
$h{ $key } = $v;
}
else {
push @unresolved, [ $key, $ref ];
}
}
else {
$value =~ s/^lit://;
$h{ $key } = $value;
}
}
$h{ $_->[0] } = $h{ $_->[1] } foreach grep { exists $h{ $_->[0] }; } @unresolved;
return wantarray ? %h : \%h;
}
要演示某些功能,请执行以下操作:
my %hash
= make_hash(
'key1' => 'value1'
, 'key2' => 'value2'
, 'key3' => 'ref:key1'
, 'key4' => 'lit:ref:key2'
, 'key5' => 'lit:lit:ref:key3'
);
lit:
前缀涵盖了“如果我真的想将一个非引用的值作为'ref:so和so'
传递该怎么办?”在回答“如果我直接需要生成一个值'lit:xzy'该怎么办?”
我做到了这一点,并且我还为传递给Lit
类或类似类的数据提供了一个引用
sub Ref ($) { bless \shift, 'Ref' }
然后在make_hash
例程中,您只需检查ref($value)eq'ref'
。并按如下方式指定:
my %hash
= make_hash(
'key1' => 'value1'
, 'key2' => 'value2'
, 'key3' => Ref 'key1'
);
有许多方法可以使Perl像您希望的那样工作 答案就在错误消息中。不可以。是否希望$hash{key1}和$hash{key3}是相同的值,即对$hash{key1}的更改在$hash{key3}中也可见?不确定为什么需要在同一声明中引用另一个键值,因为您已经知道该值(即“value1”
)。如果您不想重新键入“value1”
,请在声明%hash
@MisterEd之前将其设置为变量,因为在其外部设置与hash相关的变量将使其更难维护,因为会有很多。这需要是一个自包含的散列。这样就消除了警告,但是如果您要转储数据,它会显示为:(“key2”、“value2”、“key1”、“value1”、“key3”、“undf”)@SteveDickinson-这两个版本中的哪一个-我说的版本不会按预期工作,或者显示如何修复的版本?是否有反对票?当我回答时,我只能看到顶级解决方案(它给出了undef)。后面的答案确实设置了值,但我希望一次设置散列的全部内容。@DVK=>您可以使用hash::Util::hv_store
使多个键指向同一内存,而无需任何关联或显式引用。@EricStrom-True,这是真的。但请参阅我对您的答案+1的评论,以了解优秀的技术点。虚拟-1,因为如果你必须这样做,你最好有一个很好的理由不重新设计你的数据结构以使其更干净。@DVK=>我完全同意这种使用hv\u store
的方式应该远离大多数正常的数据结构,但也有一些用途。例如,当我编写时,它就派上了用场。+1表示非源代码过滤器模块。Beats-tie::我一直在想的hash。这基本上是我正在尝试做的事情。但是什么是上光课?此外,如果我尝试底部的“ref”示例,我会在引用“sub ref”时遇到以下错误:尝试修改只读值
@SteveDickinson,为什么需要修改它?这是一把钥匙。您只需解引用它就可以得到散列值。只要我坚持引用Perl5.14,我在Perl5.14中就没有问题。我不需要修改它。我只是简单地说明上面发布的“sub-Ref”的行为。下面更正的子代码对我来说很有用:sub-Ref($){my$value=shift;bless\$value,'Ref'}
此外,我在make_散列子代码中添加了以下代码以完成它:…}else{$value=~s/^lit://;if(ref($value)eq'ref'){$h{$key}=$h{$$value};}else{$h{$key}=$value;}
谢谢你把我引向正确的方向。@SteveDickins
my %hash
= make_hash(
'key1' => 'value1'
, 'key2' => 'value2'
, 'key3' => Ref 'key1'
);