我有三个哈希,我想将每个哈希分解成一个Hash of Arrays。每个都可以通过split函数传递给子程序,但是这需要调用3次相同的子程序。我试图遍历每个哈希并将它们拆分但没有成功。是否可以在不调用子程序的情况下执行此操作?我试过的代码是:
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
my %hash1 = (
A => "AAAAAAAAAA",
B => "AAAAANAAAA",
C => "AAAAAXAAAA",
D => "AAXAAAAAAA",
E => "AAAAAAAAAX",
);
my %hash2 = (
F => "BBBBBBBBBB",
G => "BBBBBBBBBB",
H => "BBXBBBBBBB",
I => "BBBBBBBBBB",
J => "AAAAANAAAA",
);
foreach my $ref ( \%hash1, \%hash2 ) {
while ( my ($key, $value) = each %$ref) {
@{ $ref->{$key} } = split (//, $value );
}
}
print Dumper %hash1;
但发出警告:
Can't use string ("AAAAAAAAAA") as an ARRAY ref while "strict refs" in use
提前致谢。
答案 0 :(得分:9)
您的错误在于您获取的密钥$ref->{$key}
的值为AAAAAAA
等,并将其用作@{ ... }
大括号的参考。您需要直接分配到$ref->{$key}
。
由于您要将原始值拆分为列表,因此需要一个数组来存储它。您可以通过使用命名数组,词法范围或匿名数组来执行此操作。我的选择是使用匿名数组,但命名数组可能看起来更具可读性:
foreach my $ref ( \%hash1, \%hash2 ) {
while ( my ($key, $value) = each %$ref) {
$ref->{$key} = [ split (//, $value ) ]; # using anonymous array
# my @list = split (//, $value );
# $ref->{$key} = \@list; # using named array
}
}
这个过程会覆盖原始值,但我认为这就是你想要的。
实现同样目标的更直接的方法是:
$_ = [ split // ] for values %hash1, values %hash2;
这里我们(ab)使用for
循环中的元素对原始变量别名的事实,并简单地以与上面相同的方式覆盖值。
如果压缩格式是不需要的,则更详细的替代方法是:
for my $value (values %hash1, values %hash2) {
$value = [ split //, $value ];
}
答案 1 :(得分:1)
假设我正确理解了你想做什么,你可以使用hash slicing并执行以下操作:
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
my %hash1 = (
A => "AAAAAAAAAA",
B => "AAAAANAAAA",
C => "AAAAAXAAAA",
D => "AAXAAAAAAA",
E => "AAAAAAAAAX",
);
my %hash2 = (
F => "BBBBBBBBBB",
G => "BBBBBBBBBB",
H => "BBXBBBBBBB",
I => "BBBBBBBBBB",
J => "AAAAANAAAA",
);
foreach my $ref ( \%hash1, \%hash2 ) {
my @keys = keys %$ref;
@$ref{@keys} = map { [split //, $ref->{$_}] } @keys;
}
print Dumper \%hash1;
print Dumper \%hash2;
这就像写作:
foreach my $ref ( \%hash1, \%hash2 ) {
my @keys = keys %$ref;
foreach my $key (@keys) {
my @arr = split //, $ref->{$key};
$ref->{$key} = \@arr;
}
}
更简单。