我是使用perl的新手,我正在尝试从tsv构建哈希哈希。我当前的过程是读入一个文件并构造一个哈希,然后将其插入另一个哈希。
my %hoh = ();
while (my $line = <$tsv>)
{
chomp $line;
my %hash;
my @data = split "\t", $line;
my $id;
my $iter = each_array(@columns, @data);
while(my($k, $v) = $iter->())
{
$hash{$k} = $v;
if($k eq 'Id')
{
$id = $v;
}
}
$hoh{$id} = %hash;
}
print "dump: ", Dumper(%hoh);
输出:
dump
$VAR1 = '1234567890';
$VAR2 = '17/32';
$VAR3 = '1234567891';
$VAR4 = '17/32';
.....
而不是我期望的那样:
dump
{
'1234567890' => {
'k1' => 'v1',
'k2' => 'v2',
'k3' => 'v3',
'k4' => 'v4',
'id' => '1234567890'
},
'1234567891' => {
'k1' => 'v1',
'k2' => 'v2',
'k3' => 'v3',
'k4' => 'v4',
'id' => '1234567891'
},
........
};
我有限的理解是,当我{%}}插入%hash的引用时?我究竟做错了什么?还有一种更简洁的方法可以将我的列和数据数组用作我的%哈希对象中的键值对吗?
- 提前谢谢, 尼汝
答案 0 :(得分:2)
要获得参考,您必须使用\
:
$hoh{$id} = \%hash;
%hash
是哈希,而不是对它的引用。在标量上下文中,它返回字符串X/Y
,其中X是使用的桶的数量,Y是散列中所有桶的数量(即没有用)。
答案 1 :(得分:2)
要获取对哈希变量的引用,您需要使用\%hash
(如choroba所说)。
为列分配值的更简洁方法是分配给hash slice,如下所示:
my %hoh = ();
while (my $line = <$tsv>)
{
chomp $line;
my %hash;
@hash{@columns} = split "\t", $line;
$hoh{$hash{Id}} = \%hash;
}
print "dump: ", Dumper(\%hoh);
哈希切片(@hash{@columns}
)与($hash{$columns[0]}, $hash{$columns[1]}, $hash{$columns[2]}, ...)
基本相同,直到您拥有的列数都很多。通过分配,我将split
的第一个值分配给$hash{$columns[0]}
,将第二个值分配给$hash{$columns[1]}
,依此类推。它与while ... $iter
循环完全相同,只是没有显式循环(并且它不提取$id
)。
无需在循环内比较每个$k
到'Id'
;只需将其作为普通字段存储在哈希中,然后使用$hash{Id}
将其提取出来。 (旁白:您的列标题是Id
还是id
?您在循环中使用Id
,但在预期输出中使用id
。)
如果您不想在单个条目中保留Id
字段,可以使用delete(从哈希中删除密钥并返回值):
$hoh{delete $hash{Id}} = \%hash;
答案 2 :(得分:1)
查看Perl中包含的文档。命令perldoc
非常有用。您也可以查看Perldoc网页。
其中一个教程是关于Perl references的教程。这有助于澄清您的许多问题并解释有关引用和解除引用的信息。
我还建议您查看CPAN。这是各种Perl模块的存档,可以执行许多不同的任务。看看Text::CSV。该模块将完全按照您的要求执行,即使它显示“CSV”,它也可以使用制表符分隔文件。
你错过了在你想要引用的哈希前面斜杠。你有:
$hoh{$id} = %hash;
可能想要:
$hoh{$id} = \%hash;
另外,当您执行散列的Data::Dumper
时,您应该在对散列的引用上执行此操作。在内部,散列和数组在完成Data :: Dumper转储时具有类似的结构。
你有:
print "dump: ", Dumper(%hoh);
你应该:
print "dump: ", Dumper( \%hoh );
我对该计划的尝试:
#! /usr/bin/env perl
#
use warnings;
use strict;
use autodie;
use feature qw(say);
use Data::Dumper;
use constant {
FILE => "test.txt",
};
open my $fh, "<", FILE;
#
# First line with headers
#
my $line = <$fh>;
chomp $line;
my @headers = split /\t/, $line;
my %hash_of_hashes;
#
# Rest of file
#
while ( my $line = <$fh> ) {
chomp $line;
my %line_hash;
my @values = split /\t/, $line;
for my $index ( ( 0..$#values ) ) {
$line_hash{ $headers[$index] } = $values[ $index ];
}
$hash_of_hashes{ $line_hash{id} } = \%line_hash;
}
say Dumper \%hash_of_hashes;
答案 3 :(得分:0)
如果在变量超出范围之前的最后一行中这样做,则应该只存储对变量的引用。在您的脚本中,您在while循环中声明%hash
,因此将此语句作为循环中的最后一个是安全的:
$hoh{$id} = \%hash;
如果它不是最后一个语句(或者您不确定它是否安全),请创建一个匿名结构来保存变量的内容:
$hoh{$id} = { %hash };
这会生成%hash
的副本,速度较慢,但对其进行的任何后续更改都不会影响您存储的内容。