使用数组值进行 Perl 哈希的最佳实践是什么?

发布于 2024-09-26 08:46:38 字数 204 浏览 5 评论 0 原文

解决这个问题的最佳实践是什么?

    if (... ) 
   { 
    push (@{$hash{'key'}}, @array ) ; 
     }
    else 
     {
     $hash{'key'} =""; 
 }

将一个元素存储为数组或将一个元素存储为散列中的双引号是一种不好的做法吗?

What is the best practise to solve this?

    if (... ) 
   { 
    push (@{$hash{'key'}}, @array ) ; 
     }
    else 
     {
     $hash{'key'} =""; 
 }

Is that bad practise for storing one element is array or one is just double quote in hash?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

浅紫色的梦幻 2024-10-03 08:46:38

我不确定我是否理解你的问题,但我现在会按字面意思回答它......

my @array = (1, 2, 3, 4);
my $arrayRef = \@array;     # alternatively: my $arrayRef = [1, 2, 3, 4];

my %hash;

$hash{'key'} = $arrayRef;   # or again: $hash{'key'} = [1, 2, 3, 4]; or $hash{'key'} = \@array;

问题的关键是数组或哈希采用标量值......所以你需要引用你的数组或散列并将其用作值。

请参阅 perlrefperlreftut 了解更多信息。


编辑:是的,您可以添加空字符串作为某些键的值和其他键的引用(数组或散列,甚至标量,类型团/文件句柄或其他标量。无论哪种方式)。它们仍然是标量。

您需要查看 ref 函数来计算了解如何消除引用类型和普通标量之间的歧义。

I'm not sure I understand your question, but I'll answer it literally as asked for now...

my @array = (1, 2, 3, 4);
my $arrayRef = \@array;     # alternatively: my $arrayRef = [1, 2, 3, 4];

my %hash;

$hash{'key'} = $arrayRef;   # or again: $hash{'key'} = [1, 2, 3, 4]; or $hash{'key'} = \@array;

The crux of the problem is that arrays or hashes take scalar values... so you need to take a reference to your array or hash and use that as the value.

See perlref and perlreftut for more information.


EDIT: Yes, you can add empty strings as values for some keys and references (to arrays or hashes, or even scalars, typeglobs/filehandles, or other scalars. Either way) for other keys. They're all still scalars.

You'll want to look at the ref function for figuring out how to disambiguate between the reference types and normal scalars.

素衣风尘叹 2024-10-03 08:46:38

使用显式数组引用可能更简单:

my $arr_ref = \@array;
$hash{'key'} = $arr_ref;

实际上,执行上述操作并使用 push 会产生相同的数据结构:

my @array = qw/ one two three four five /;
my $arr_ref = \@array;
my %hash;
my %hash2;
$hash{'key'} = $arr_ref;
print Dumper \%hash;
push @{$hash2{'key'}}, @array;
print Dumper \%hash2;

这给出:

$VAR1 = {
          'key' => [
                     'one',
                     'two',
                     'three',
                     'four',
                     'five'
                   ]
        };
$VAR1 = {
          'key' => [
                     'one',
                     'two',
                     'three',
                     'four',
                     'five'
                   ]
        };

使用显式数组引用使用更少的字符,并且比 更容易阅读>push @{$hash{'key'}}, @array 构造,IMO。

编辑:对于您的 else{} 块,分配空字符串可能不太理想。跳过 if-else 构造,稍后当您访问哈希中的值时,执行 if( Defined( $hash{'key '} ) ) 检查。这更接近标准 Perl 习惯用法,并且您不会浪费内存在散列中存储空字符串。

相反,您必须使用 ref() 来找出值中包含哪些类型的数据,这比仅进行定义性检查不太清楚。

It's probably simpler to use explicit array references:

my $arr_ref = \@array;
$hash{'key'} = $arr_ref;

Actually, doing the above and using push result in the same data structure:

my @array = qw/ one two three four five /;
my $arr_ref = \@array;
my %hash;
my %hash2;
$hash{'key'} = $arr_ref;
print Dumper \%hash;
push @{$hash2{'key'}}, @array;
print Dumper \%hash2;

This gives:

$VAR1 = {
          'key' => [
                     'one',
                     'two',
                     'three',
                     'four',
                     'five'
                   ]
        };
$VAR1 = {
          'key' => [
                     'one',
                     'two',
                     'three',
                     'four',
                     'five'
                   ]
        };

Using explicit array references uses fewer characters and is easier to read than the push @{$hash{'key'}}, @array construct, IMO.

Edit: For your else{} block, it's probably less than ideal to assign an empty string. It would be a lot easier to just skip the if-else construct and, later on when you're accessing values in the hash, to do a if( defined( $hash{'key'} ) ) check. That's a lot closer to standard Perl idiom, and you don't waste memory storing empty strings in your hash.

Instead, you'll have to use ref() to find out what kind of data you have in your value, and that is less clear than just doing a defined-ness check.

抱着落日 2024-10-03 08:46:38

我不确定您的目标是什么,但有几件事需要考虑。

首先,如果要存储数组,您想要存储对原始值的引用还是原始值的副本?在任何一种情况下,我都倾向于避免取消引用语法并尽可能获取引用:

 $hash{key} = \@array;  # just a reference

 use Clone; # or a similar module
 $hash{key} = clone( \@array );

接下来,您是否要添加到已经存在的值,即使它是单个值?如果您要拥有数组值,即使您只有一个元素,我也会将所有值设为数组。然后,您不必决定要做什么,并且可以删除特殊情况:

 $hash{key} = [] unless defined $hash{key};
 push @{ $hash{key} }, @values;

这可能是您的“最佳实践”答案,这通常是删除尽可能多的特殊情况和额外逻辑的技术。当我在模块中执行此类操作时,我通常会使用一个 add_value 方法来封装这种魔法,这样我就不必多次查看或键入它。

如果散列键中已经有非引用值,也很容易修复:

 if( defined $hash{key} and ! ref $hash{key} ) {
      $hash{key} = [ $hash{key} ];
      }

如果您已经有想要在数组中的非数组引用值,则可以执行类似的操作。也许您希望匿名哈希成为数组元素之一:

 if( defined $hash{key} and ref $hash{key} eq ref {} ) {
      $hash{key} = [ $hash{key} ];
      }

I'm not sure what your goal is, but there are several things to consider.

First, if you are going to store an array, do you want to store a reference to the original value or a copy of the original values? In either case, I prefer to avoid the dereferencing syntax and take references when I can:

 $hash{key} = \@array;  # just a reference

 use Clone; # or a similar module
 $hash{key} = clone( \@array );

Next, do you want to add to the values that exist already, even if it's a single value? If you are going to have array values, I'd make all the values arrays even if you have a single element. Then you don't have to decide what to do and you remove a special case:

 $hash{key} = [] unless defined $hash{key};
 push @{ $hash{key} }, @values;

That might be your "best practice" answer, which is often the technique that removes as many special cases and extra logic as possible. When I do this sort of thing in a module, I typically have a add_value method that encapsulates this magic where I don't have to see it or type it more than once.

If you already have a non-reference value in the hash key, that's easy to fix too:

 if( defined $hash{key} and ! ref $hash{key} ) {
      $hash{key} = [ $hash{key} ];
      }

If you already have non-array reference values that you want to be in the array, you do something similar. Maybe you want an anonymous hash to be one of the array elements:

 if( defined $hash{key} and ref $hash{key} eq ref {} ) {
      $hash{key} = [ $hash{key} ];
      }
開玄 2024-10-03 08:46:38

处理修订后的符号:

if (... ) 
{ 
    push (@{$hash{'key'}}, @array); 
}
else 
{
    $hash{'key'} = "";
}

我们可以立即看出您没有遵循保护新手(和专家!)免受自己错误影响的标准建议。您使用的是符号引用,这不是一个好主意。

use strict;
use warnings;

my %hash = ( key => "value" );
my @array = ( 1, "abc", 2 );
my @value = ( 22, 23, 24 );

push(@{$hash{'key'}}, @array);

foreach my $key (sort keys %hash) { print "$key = $hash{$key}\n"; }
foreach my $value (@array)        { print "array $value\n"; }
foreach my $value (@value)        { print "value $value\n"; }

这不会运行:

Can't use string ("value") as an ARRAY ref while "strict refs" in use at xx.pl line 8.

我不确定我能否弄清楚您想要实现的目标。即使您删除了“use strict;”警告,显示的代码未检测到 push 操作的更改。

use warnings;

my %hash = ( key => "value" );
my @array = ( 1, "abc", 2 );
my @value = ( 22, 23, 24 );

push @{$hash{'key'}}, @array;

foreach my $key (sort keys %hash)   { print "$key = $hash{$key}\n"; }
foreach my $value (@array)          { print "array $value\n"; }
foreach my $value (@value)          { print "value $value\n"; }
foreach my $value (@{$hash{'key'}}) { print "h_key $value\n"; }

push @value, @array;

foreach my $key (sort keys %hash) { print "$key = $hash{$key}\n"; }
foreach my $value (@array)        { print "array $value\n"; }
foreach my $value (@value)        { print "value $value\n"; }

输出:

key = value
array 1
array abc
array 2
value 22
value 23
value 24
h_key 1
h_key abc
h_key 2
key = value
array 1
array abc
array 2
value 22
value 23
value 24
value 1
value abc
value 2

我不确定那里发生了什么。

Dealing with the revised notation:

if (... ) 
{ 
    push (@{$hash{'key'}}, @array); 
}
else 
{
    $hash{'key'} = "";
}

we can immediately tell that you are not following the standard advice that protects novices (and experts!) from their own mistakes. You're using a symbolic reference, which is not a good idea.

use strict;
use warnings;

my %hash = ( key => "value" );
my @array = ( 1, "abc", 2 );
my @value = ( 22, 23, 24 );

push(@{$hash{'key'}}, @array);

foreach my $key (sort keys %hash) { print "$key = $hash{$key}\n"; }
foreach my $value (@array)        { print "array $value\n"; }
foreach my $value (@value)        { print "value $value\n"; }

This does not run:

Can't use string ("value") as an ARRAY ref while "strict refs" in use at xx.pl line 8.

I'm not sure I can work out what you were trying to achieve. Even if you remove the 'use strict;' warning, the code shown does not detect a change from the push operation.

use warnings;

my %hash = ( key => "value" );
my @array = ( 1, "abc", 2 );
my @value = ( 22, 23, 24 );

push @{$hash{'key'}}, @array;

foreach my $key (sort keys %hash)   { print "$key = $hash{$key}\n"; }
foreach my $value (@array)          { print "array $value\n"; }
foreach my $value (@value)          { print "value $value\n"; }
foreach my $value (@{$hash{'key'}}) { print "h_key $value\n"; }

push @value, @array;

foreach my $key (sort keys %hash) { print "$key = $hash{$key}\n"; }
foreach my $value (@array)        { print "array $value\n"; }
foreach my $value (@value)        { print "value $value\n"; }

Output:

key = value
array 1
array abc
array 2
value 22
value 23
value 24
h_key 1
h_key abc
h_key 2
key = value
array 1
array abc
array 2
value 22
value 23
value 24
value 1
value abc
value 2

I'm not sure what is going on there.

风吹过旳痕迹 2024-10-03 08:46:38

如果您的问题是如何将之前存储的空字符串值替换为可以将值推入其中的数组,这可能是最好的方法:

if ( ... ) { 
    my $r = \$hash{ $key }; # $hash{ $key } autoviv-ed
    $r   = [] unless ref $r;
    push @$r, @values;
}
else { 
    $hash{ $key } = "";
}
  • 我避免使用多个哈希查找 -通过保存自动激活插槽的副本来进行更新。
  • 请注意,代码依赖于标量或数组,它们是存储在 %hash 中的整个事物。

If your problem is how do you replace a empty string value you had stored before with an array onto which you can push your values, this might be the best way to do it:

if ( ... ) { 
    my $r = \$hash{ $key }; # $hash{ $key } autoviv-ed
    $r   = [] unless ref $r;
    push @$r, @values;
}
else { 
    $hash{ $key } = "";
}
  • I avoid multiple hash look-ups by saving a copy of the auto-vivified slot.
  • Note the code relies on a scalar or an array being the entire universe of things stored in %hash.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文