我正在尝试使用具有数组值概念的哈希散列来生成哈希。我不确定我的语法是否正确。
下面是我希望应该创建带有数组值的哈希哈希值的代码部分。
use strict;
%hash=();
open IN, "samplefile.txt" or die "cannot open file:$!";
while(<IN>){
chomp $_;
my @split=split("\t", $_);
$hash{$split[0]}{$split[1]}=push @{ $hash{$split[0]}{$split[1]} },$split[2];
push(@array, $split[1]);
}
示例数据集:
4 10 2
9 4 3
4 3 2
4 3 8
4 10 5
4 5 2
预期哈希。
%hash=(
'4'=> {
'10'=>'2, 5'
'5' => '2'
'3' => '2,8'
}
'9'=>{
'4'=>'3'
}
)
答案 0 :(得分:6)
我认为你真的想要
%hash = (
'4' => {
'10' => [ 2, 5 ],
'5' => [ 2 ],
'3' => [ 2, 8 ],
},
'9' => {
'4' => [ 3 ],
},
);
解决方案:
my %hash;
while (<>) {
my @F = split;
push @{ $hash{ $F[0] }{ $F[1] } }, $F[2];
}
由于自动更新,它将根据需要自动创建哈希和数组。
如果你真的想要字符串而不是数组,那么之后你总是可以使用join ','
。
for my $k1 (keys(%hash)) {
for my $k2 (keys(${ $hash{$k1} })) {
$hash{$k1}{$k2} = join(',', @{ $hash{$k1}{$k2} });
}
}
答案 1 :(得分:2)
如果您正在使用push
,则不应使用等号(除非您希望推送的项目数量)。那告诉我那里有一个问题。您可能对您的结构感到有些困惑。您要么将数据推送到数组引用中,要么就是要加入项目并将其推送到另一个结构中。你所写的内容有点难以理解,因为语法很难理解。
看起来你想要玩弄参考文献,看看你是否能掌握它们。当您处理这样的复杂结构时,如果您有一些......呃...... 真实世界数据,它会更容易理解。让我们创建一个数组哈希的真实世界哈希,这将更容易跟踪。
让我们制作一个包含人物的哈希。哈希将包含数据,并将由该人的姓名键入。我们称之为%people
。我们的哈希,鲍勃和珍妮特将有两个人。鲍勃和珍妮特有各种地址和电话号码。我们将在哈希中有一个引用,其中包含名为PHONE
和ADDRESS
的数据字段的名称。
$people{Bob}->{ADDRESS}; # Bob's addresses
$people{Bob}->{PHONE}; # Bob's phone numbers
$people{Janet}->{ADDRESS}; # Janet's Addresses
$people{Janet}->{PHONE}; # Janet's Phone numbers
请注意箭头语法。这告诉您$people{Bob}
包含对其他哈希的引用,而不仅仅是标量数据。
接下来,Bob和Janet可能有多个地址和电话号码,因此我们不会存储一个电话号码,而是$people{Bob}->{PHONE}
存储对一系列电话号码的引用,$people{Bob}->{ADDRESS}
将包含对地址数组的引用。
这是一个读取数据的简短程序。每当一行以person:
开头时,我假设以下数据将用于该人。一个人可以拥有地址和电话号码。我将它们作为数组存储在正确的哈希值下。
正如ikegami所说,Perl拥有所谓的 auto vivification ,让Perl能够确切地指出你指向的是哪种类型的引用。但是,我喜欢说明我期望数据结构将用于文档目的。我的程序中的以下陈述并非真的有必要,但我觉得很有用:
$people{$person} = {}; # This is a reference to another array
和
if ( not exists $people{$person}->{ADDRESS} ) {
$people{$person}->{ADDRESS} = []; #This is a reference to an array
}
这是我的计划:
#! /usr/bin/env perl
#
use strict;
use warnings;
use Data::Dumper;
use feature qw(say);
my %people;
my $person;
while ( my $line = <DATA> ) {
chomp $line;
my ( $type, $data ) = split /:\s*/, $line;
if ( $type eq "person" ) {
$person = $data;
$people{$person} = {}; # This is a reference to another array
}
if ( $type eq "address" ) {
if ( not exists $people{$person}->{ADDRESS} ) {
$people{$person}->{ADDRESS} = []; #This is a reference to an array
}
push @{ $people{$person}->{ADDRESS} }, $data;
}
if ( $type eq "phone" ) {
if ( not exists $people{$person}->{PHONE} ) {
$people{$person}->{PHONE} = []; #This is a reference to an array
}
push @{ $people{$person}->{PHONE} }, $data;
}
}
say Dumper \%people;
__DATA__
person: Bob
address: 120 Main Street, Suburbville CO
address: 123 Wage Slave Lane, Industry CO
address: 1 Beach Hut Road, Getaway CA
phone: 555-1111
phone: 555-2222
person: Janet
address: 230 Oak Tree Road, Gloomsburg CO
address: 544 Initech Road, Businesstown CO
phone: 555-3333
phone: 555-4444
这会产生:
$VAR1 = {
'Bob' => {
'PHONE' => [
'555-1111',
'555-2222'
],
'ADDRESS' => [
'120 Main Street, Suburbville CO',
'123 Wage Slave Lane, Industry CO',
'1 Beach Hut Road, Getaway CA'
]
},
'Janet' => {
'PHONE' => [
'555-3333',
'555-4444'
],
'ADDRESS' => [
'230 Oak Tree Road, Gloomsburg CO',
'544 Initech Road, Businesstown CO'
]
}
};