文件处理 perl - split 产生非常小的数组
File processing perl - split produces very small arrays
美好的一天。我有一个大文本文件要处理,组织方式如下:
A
B 87368911
C 165368993 165369000 165369007 165369014 165369021 165369028
D 3299941
E 3221521
F 5909327
G 14740025 14740019 14740031 14740037
H 4446477 4640745
我想把它拆分成数组的散列,以第一列为键,如果有可迭代数组中的值(对于 A,有 none ,如您所见)。为此,我制作了如下代码(略有截肢,我明明打开文件有周边代码):
my %resolvedreads;
while (my $line = <IN>) {
my @thisline = $line =~ m/(\S+)/g;
$resolvedreads{$thisline[0]} = @thisline[1 .. $#thisline];
print join "\t", @{$resolvedreads{$thisline[0]}}, "\n";
}
我什至没有真正测试过这个,因为它看起来太微不足道了。显然我应该有,因为它给了我这个:
Use of uninitialized value $thisline[0] in hash element at resolved_reads_purifier.pl line X-1, <IN> line 1.
Use of uninitialized value $thisline[0] in hash element at resolved_reads_purifier.pl line X, <IN> line 1.
Can't use an undefined value as an ARRAY reference at resolved_reads_purifier.pl line X, <IN> line 1.
我发现自己对此有些困惑。进一步调查发现,该行确实被拆分了,但是每个数组的长度都是1或2。
那么是什么原因呢?我觉得我在这里错过了一些基本的东西,而且我已经无能为力了。尽管在我看来几乎完全相同,但我之前的代码实际上已编译。
$resolvedreads{$thisline[0]} = @thisline[1 .. $#thisline];
将一个数组赋值给一个标量上下文中的哈希值,其实和
是一样的
$resolvedreads{$thisline[0]} = scalar @thisline[1 .. $#thisline];
或
$resolvedreads{$thisline[0]} = $#thisline;
$resolvedreads{$thisline[0]} = $thisline[$#thisline];
从你的其余部分 post 看来你想为散列值分配一个数组引用
$resolvedreads{$thisline[0]} = [ @thisline[1 .. $#thisline] ];
同样,您可以将列表分配给列表上下文中的列表
@{$resolvedreads{$thisline[0]}} = @thisline[1 .. $#thisline];
所以我看到了几件事。上面提到的分配数组时的标量与列表上下文。另一件事是您的切片 [1...#@array] 以“1”开头,但 A 行不存在索引 1,因此您的错误消息。这是工作代码:
use Modern::Perl '2013';
use Data::Dumper;
my $text = 'A
B 87368911
C 165368993 165369000 165369007 165369014 165369021 165369028
D 3299941
E 3221521
F 5909327
G 14740025 14740019 14740031 14740037
H 4446477 4640745';
my $fh;
open($fh, '<', $text);
my %resolvedreads;
while (my $line = <$fh>) {
chomp $line;
my @thisline = $line =~ m/(\S+)/g;
my $index = shift @thisline;
$resolvedreads{$index} = \@thisline;
}
say Dumper(\%resolvedreads);
问题是,当一个文件记录只有一个字段时,$#thisline
为零,所以 @thisline[1 .. $#thisline]
是 @thisline[1 .. 0]
,这是一个空列表。将其分配给给定的标量 undef
除此之外还有一个问题
$resolvedreads{$thisline[0]} = @thisline[1 .. $#thisline]
因为您将一个列表分配给一个标量,您通常只会得到列表的最后一个元素,即 $thisline[-1]
。此时你真的应该分配一个数组引用
这就是我对您的问题进行编码的方式
use strict;
use warnings;
my %resolvedreads;
while ( <DATA>) {
my ($key, @values) = split;
next unless defined $key; # Skip blank records
$resolvedreads{$key} = \@values;
}
use Data::Dump;
dd %resolvedreads;
__DATA__
A
B 87368911
C 165368993 165369000 165369007 165369014 165369021 165369028
D 3299941
E 3221521
F 5909327
G 14740025 14740019 14740031 14740037
H 4446477 4640745
输出
{
A => [],
B => [87368911],
C => [165368993, 165369000, 165369007, 165369014, 165369021, 165369028],
D => [3299941],
E => [3221521],
F => [5909327],
G => [14740025, 14740019, 14740031, 14740037],
H => [4446477, 4640745],
}
美好的一天。我有一个大文本文件要处理,组织方式如下:
A
B 87368911
C 165368993 165369000 165369007 165369014 165369021 165369028
D 3299941
E 3221521
F 5909327
G 14740025 14740019 14740031 14740037
H 4446477 4640745
我想把它拆分成数组的散列,以第一列为键,如果有可迭代数组中的值(对于 A,有 none ,如您所见)。为此,我制作了如下代码(略有截肢,我明明打开文件有周边代码):
my %resolvedreads;
while (my $line = <IN>) {
my @thisline = $line =~ m/(\S+)/g;
$resolvedreads{$thisline[0]} = @thisline[1 .. $#thisline];
print join "\t", @{$resolvedreads{$thisline[0]}}, "\n";
}
我什至没有真正测试过这个,因为它看起来太微不足道了。显然我应该有,因为它给了我这个:
Use of uninitialized value $thisline[0] in hash element at resolved_reads_purifier.pl line X-1, <IN> line 1.
Use of uninitialized value $thisline[0] in hash element at resolved_reads_purifier.pl line X, <IN> line 1.
Can't use an undefined value as an ARRAY reference at resolved_reads_purifier.pl line X, <IN> line 1.
我发现自己对此有些困惑。进一步调查发现,该行确实被拆分了,但是每个数组的长度都是1或2。
那么是什么原因呢?我觉得我在这里错过了一些基本的东西,而且我已经无能为力了。尽管在我看来几乎完全相同,但我之前的代码实际上已编译。
$resolvedreads{$thisline[0]} = @thisline[1 .. $#thisline];
将一个数组赋值给一个标量上下文中的哈希值,其实和
是一样的$resolvedreads{$thisline[0]} = scalar @thisline[1 .. $#thisline];
或
$resolvedreads{$thisline[0]} = $#thisline;
$resolvedreads{$thisline[0]} = $thisline[$#thisline];
从你的其余部分 post 看来你想为散列值分配一个数组引用
$resolvedreads{$thisline[0]} = [ @thisline[1 .. $#thisline] ];
同样,您可以将列表分配给列表上下文中的列表
@{$resolvedreads{$thisline[0]}} = @thisline[1 .. $#thisline];
所以我看到了几件事。上面提到的分配数组时的标量与列表上下文。另一件事是您的切片 [1...#@array] 以“1”开头,但 A 行不存在索引 1,因此您的错误消息。这是工作代码:
use Modern::Perl '2013';
use Data::Dumper;
my $text = 'A
B 87368911
C 165368993 165369000 165369007 165369014 165369021 165369028
D 3299941
E 3221521
F 5909327
G 14740025 14740019 14740031 14740037
H 4446477 4640745';
my $fh;
open($fh, '<', $text);
my %resolvedreads;
while (my $line = <$fh>) {
chomp $line;
my @thisline = $line =~ m/(\S+)/g;
my $index = shift @thisline;
$resolvedreads{$index} = \@thisline;
}
say Dumper(\%resolvedreads);
问题是,当一个文件记录只有一个字段时,$#thisline
为零,所以 @thisline[1 .. $#thisline]
是 @thisline[1 .. 0]
,这是一个空列表。将其分配给给定的标量 undef
除此之外还有一个问题
$resolvedreads{$thisline[0]} = @thisline[1 .. $#thisline]
因为您将一个列表分配给一个标量,您通常只会得到列表的最后一个元素,即 $thisline[-1]
。此时你真的应该分配一个数组引用
这就是我对您的问题进行编码的方式
use strict;
use warnings;
my %resolvedreads;
while ( <DATA>) {
my ($key, @values) = split;
next unless defined $key; # Skip blank records
$resolvedreads{$key} = \@values;
}
use Data::Dump;
dd %resolvedreads;
__DATA__
A
B 87368911
C 165368993 165369000 165369007 165369014 165369021 165369028
D 3299941
E 3221521
F 5909327
G 14740025 14740019 14740031 14740037
H 4446477 4640745
输出
{
A => [],
B => [87368911],
C => [165368993, 165369000, 165369007, 165369014, 165369021, 165369028],
D => [3299941],
E => [3221521],
F => [5909327],
G => [14740025, 14740019, 14740031, 14740037],
H => [4446477, 4640745],
}