我想要简化这个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;
有人知道这样做的方法吗?
答案 0 :(得分:4)
语法是
for my $i (0..6) {
my $variable_name = "item$i";
$user{$account_num}{$variable_name} += $$variable_name;
}
但它假设$item0
,这是包变量,它使用goes against软件开发的基本原则。
您应该使用数组。
$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];
}
答案 1 :(得分:4)
你在想它。
我可以说,因为我一直这样做:
我:如果我制造的设备能够以合适的频率振动插座,我可以将灯泡拧紧并拧开。然后我可以将设备连接到插座......
我儿子:爸爸,你为什么不用电灯开关?
如果你有一大堆名为item1
,item2
,item3
等的项目,为什么不把它作为一个项目数组呢?然后你会有$item[0]
,$item[1]
等。这会大大简化你的代码:
for item ( @items ) {
$user{$account_name}->[$item] += $items[item];
}
也许您使用item1
和item2
作为实际变量名称的替身。也许他们是$widget
和$left_handed_smoke_shifter
。在这种情况下,您可以将其设为项目的哈希值,这样您就可以$item{left_handed_smoke_shifter}
和$item{widget}
。然后,你的循环看起来像这样:
for my $item ( keys %items ) {
$user{$account_name}->{$item} += $items{$item};
}
简单易懂,易于理解。
但是,如果你真的,真的坚持你需要能够按照你坚持的方式使用变量名,请使用eval
:
$user{$account_name}->{$varible_name} = eval '$' . "$variable_name";
我只是出售长度足以让人自己悬挂的绳索。他们实际上用它做的不是我的事。
答案 2 :(得分:1)
上面代码的问题是你想使用变量的名称作为键,它可能如下所示:
for my $item ( @items ) {
$user{$account_num}{$item} = $item
}
问题是$item
的值将被用作密钥,而不是其名称。
可能的解决方案:
如果你还有一个关键名列表,这将大大简化:
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;
}
答案 3 :(得分: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>
密钥是$$_
,它使用变量间接来获取名称包含在变量中的变量的值,在本例中为$_
。
答案 4 :(得分: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";
示例输出:
Before: $VAR1 = [645,553,864,165,463,455,906]; After: $VAR1 = [656,575,897,209,518,521,983];
答案 5 :(得分:0)
最简洁的方法是使用eval
。喜欢这个
$user{$account_num}{$_} += eval "\$$_" for 'item0' .. 'item6'
但记得其他人说过的话,你不应该做这类事情。在适当的时候尽快重构代码。