这是我的文字档案:
animal, cola, husband, 36
animal, wilma, wife, 31
animal, pebbles, kid, 4
brutal, george, husband, 41
brutal, jane, wife, 39
brutal, elroy, kid, 9
cosa, homer, husband, 34
cosa, marge, wife, 37
cosa, bart, kid, 11
这就是我想要的数据结构:
%HASH = (
animal => [
{ name => "cola", role => "husband", age => 36, },
{ name => "wilma", role => "wife", age => 31, },
{ name => "pebbles", role => "kid", age => 4, },
],
brutal => [
{ name => "george", role => "husband", age => 41, },
{ name => "jane", role => "wife", age => 39, },
{ name => "elroy", role => "kid", age => 9, },
],
cosa => [
{ name => "homer", role => "husband", age => 34, },
{ name => "marge", role => "wife", age => 37, },
{ name => "bart", role => "kid", age => 11, },
],
);
我有一些代码,但我无法将它们组装成一个连贯的脚本。我只希望有人帮助我定义这个结构并理解它。
答案 0 :(得分:2)
代码:
use strict;
use warnings;
use Data::Dumper;
my %hash;
my @columns = qw(category name role age);
while (<DATA>) {
chomp;
my %temp;
@temp{@columns} = split(/\s*,\s*/);
my $key = delete($temp{category});
push(@{$hash{$key}}, \%temp);
}
print Dumper(\%hash);
__DATA__
animal, cola, husband, 36
animal, wilma, wife, 31
animal, pebbles, kid, 4
brutal, george, husband, 41
brutal, jane, wife, 39
brutal, elroy, kid, 9
cosa, homer, husband, 34
cosa, marge, wife, 37
cosa, bart, kid, 11
输出:
$VAR1 = {
'cosa' => [
{
'name' => 'homer',
'age' => '34',
'role' => 'husband'
},
{
'name' => 'marge',
'age' => '37',
'role' => 'wife'
},
{
'name' => 'bart',
'age' => '11',
'role' => 'kid'
}
],
'brutal' => [
{
'name' => 'george',
'age' => '41',
'role' => 'husband'
},
{
'name' => 'jane',
'age' => '39',
'role' => 'wife'
},
{
'name' => 'elroy',
'age' => '9',
'role' => 'kid'
}
],
'animal' => [
{
'name' => 'cola',
'age' => '36',
'role' => 'husband'
},
{
'name' => 'wilma',
'age' => '31',
'role' => 'wife'
},
{
'name' => 'pebbles',
'age' => '4',
'role' => 'kid'
}
]
};
答案 1 :(得分:2)
您显示的数据结构有一个关于它的关键规则:哈希值中的值只能是标量。
因此,要将多值变量与键相关联,请使用对该变量的引用,此处为arrayref。如果该数组中的值需要比标量更复杂,则再次使用引用,这里是hashref。†因此每个键的值是一个arrayref,其元素是hashrefs。
然后,您需要学习如何访问结构中更深层的元素。这也不是很复杂:取消引用它们然后你可以像使用数组或散列一样使用它们。
所有这些都在perldsc中,需要明确perlreftut。完整参考是perlref。
在你的问题中使用它时
use warnings;
use strict;
use Data::Dump qw(dd);
my $file = 'data.txt';
open my $fh, '<', $file or die "Can't open $file: $!";
my %result;
while (<$fh>) {
chomp;
my ($key, $name, $role, $age) = split /\s*,\s*/;
push @{$result{$key}}, { name => $name, role => $role, age => $age };
}
dd \%result;
这将打印正确的数据结构。请注意使用Data::Dump查看复杂的数据结构。最常见的模块是Data::Dumper,还有其他模块。
上面的split使用正则表达式/\s*,\s*/
作为分隔符,因此可以用逗号分隔行,可选地用空格包围。其默认值用于要拆分的字符串,即$_
请注意,我们不必“添加密钥”或使用它们的arrayref值,因为这是通过 autovivification 完成的。例如,请参阅this page和this page以及this page。 这是一个复杂的功能,如果误用就会咬人,所以请仔细阅读。
†如果数组或散列被列为数组的“元素”,它们会被“展平” - 它们的元素与所有其他给定元素合并,整个聚合列表用于填充数组,我们用所有这些元素得到一个数组。所以
my @ary = 1..3;
my %hash = (a => 10, b => 20);
# Most likely an error:
my @all = (5, @ary, %hash, 100); #--> (5, 1, 2, 3, a, 10, b, 20, 100)
其中键值对可以以任何顺序出现,因为哈希本质上是无序的。
相反,我们引用数组和哈希并写入
my @all = (5, \@ary, \%hash, 100);
现在@ary
和%hash
的内容保持个性,可以根据需要恢复。