1

我有这个要简化的 Perl 代码块。它是子程序的一部分,其中一系列参数被添加到哈希值的哈希值中。

$user{$account_num}{'item0'} += $item0;
$user{$account_num}{'item1'} += $item1;
$user{$account_num}{'item2'} += $item2;
$user{$account_num}{'item3'} += $item3;
$user{$account_num}{'item4'} += $item4;
$user{$account_num}{'item5'} += $item5;
$user{$account_num}{'item6'} += $item6;

您可以看到变量名称与键名称相同。我似乎记得曾经看过一个朋友在一行中做这种事情。就像是:

[looping through input arguments]:
$user{$account_num}{'variable_name'} += $variable_name;

有人知道这样做的方法吗?

4

6 回答 6

4

你想多了。

我可以说,因为我一直这样做:

:如果我制造一个可以以正确的频率振动插座的设备,我可以让那个灯泡拧上和拧下。然后我可以将设备连接到插座...

我儿子:爸爸,你为什么不用电灯开关?

如果你有一堆名为item1, item2,item3等的项目。为什么不把它变成一个项目数组呢?然后您将拥有$item[0],$item[1]等。这将大大简化您的代码:

for item ( @items ) {
    $user{$account_name}->[$item] += $items[item];
}

也许您使用item1anditem2作为实际变量名的替代品。也许他们是$widget$left_handed_smoke_shifter。在这种情况下,您可以将其设为项目的哈希,因此您将拥有$item{left_handed_smoke_shifter}and $item{widget}。然后,您的循环将如下所示:

for my $item ( keys %items ) {
    $user{$account_name}->{$item} += $items{$item};
}

简单,易于理解和维护。

但是,如果您真的坚持认为您需要能够按照您坚持的方式使用变量名,请使用eval

$user{$account_name}->{$varible_name} = eval '$' . "$variable_name";

我只卖足够长的绳子,以便有人用它上吊。他们实际上用它做什么与我无关。

于 2013-08-23T18:12:48.847 回答
4

语法是

for my $i (0..6) {
   my $variable_name = "item$i";
   $user{$account_num}{$variable_name} += $$variable_name;
}

但它假设$item0等是包变量,并且它的使用违背了软件开发的基本原则。


您应该使用数组。

$user{$account_num}{'item0'} += $items[0];
$user{$account_num}{'item1'} += $items[1];
$user{$account_num}{'item2'} += $items[2];
$user{$account_num}{'item3'} += $items[3];
$user{$account_num}{'item4'} += $items[4];
$user{$account_num}{'item5'} += $items[5];
$user{$account_num}{'item6'} += $items[6];

它允许您使用

for my $i (0..$#items) {
    $user{$account_num}{"item$i"} += $items[$i];
}
于 2013-08-23T18:02:21.317 回答
1
#!/usr/bin/env perl

use strict;
use warnings;

use Data::Dumper;
$Data::Dumper::Indent = 0;

my %user = (
    '0022334401' => [ map int(1000 * rand), 1 .. 7 ],
    '1177459393' => [ map int(1000 * rand), 1 .. 7 ],
);

my $account_id = '0022334401';

print "Before:\n", Dumper($user{$account_id}) ,"\n";

my @vals = (11, 22, 33, 44, 55, 66, 77);

# done setting up. now, update each value for $user{$account_id}
# by adding the value at the corresponding index in @vals

$user{$account_id}[$_] += $vals[$_] for 0 .. $#vals;

print "After:\n", Dumper($user{$account_id}), "\n";

样本输出:

前:
$VAR1 = [645,553,864,165,463,455,906];
后:
$VAR1 = [656,575,897,209,518,521,983];
于 2013-08-23T17:57:34.190 回答
1

这是 Perl 调试器中的一个简单示例:

main::(-e:1):   0
  DB<1> @a=('v1', 'v2', 'v3', 'v4')

  DB<2> x @a
0  'v1'
1  'v2'
2  'v3'
3  'v4'
  DB<3> $v1=10
  DB<4> $v2=20
  DB<5> $v3=30
  DB<6> $v4=40

  DB<7> for (@a) { $hash{$_} += $$_ }

  DB<8> x %hash
0  'v4'
1  40
2  'v1'
3  10
4  'v2'
5  20
6  'v3'
7  30
  DB<10>

关键是$$_,它使用变量间接获取名称包含在变量中的变量的值,在本例中为$_

于 2013-08-23T17:33:52.483 回答
1

上面代码的问题是你想使用变量的名称作为键,它可能看起来像这样:

for my $item ( @items ) {
   $user{$account_num}{$item} = $item
}

问题是$items 值将用作键,而不是它的名称。

可能的解决方案:

如果您还有一个键名列表,这将大大简化:

my @keys = qw(item0 item1 item2 item3 item4 item5 item6);

现在假设你实际上有所有这些项目进入你的子程序,你可以轻松地循环

# 1
sub update_items {
   my @items = @_;

   for my $k ( @keys ) { 
      my $item = shift @items;          # take an item from the front
      $user{$account_num}{$k} += $item; # update
   }
}

或者,您可以使用一种称为hash-slicing在列表上下文中获取哈希并将值列表分配给键列表的技术:

# 2
sub update_items {
   my @items = @_;

   # update all keys of @keys with all values of @items
   @user{$account_num}{@keys} += @items;
}
于 2013-08-23T17:31:35.550 回答
0

最整洁的方法是使用eval. 像这样

$user{$account_num}{$_} += eval "\$$_" for 'item0' .. 'item6'

请记住其他人所说的,你不应该做这种事情。在适当的时候重构代码。

于 2013-08-23T18:57:27.987 回答