Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 使用另一个哈希值定义哈希值。_Perl_Perl Data Structures - Fatal编程技术网

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'
    );