尝试运行下面的代码时,我从Perl收到以下错误
Use of uninitialized value within @words in concatenation (.) or string...
它引用了我尝试创建由三个单词序列组成的数组的行(以$trigrams
开头的行)。任何人都可以帮我解决问题吗?
my %hash;
my @words;
my $word;
my @trigrams;
my $i = 0;
while (<>) {
@words = split;
foreach $word (@words) {
$hash{$word}++;
# Now trying to create the distinct six-grams in the 10-K.
$trigrams[$i] = join " ", $words[$i], $words[$i + 1], $words[$i + 2];
print "$words[$i]\n";
$i++;
}
}
答案 0 :(得分:5)
所有发生的事情都是你从阵列@words
的末尾掉下来。您正在为@words
的每个元素执行循环,因此$i
的值从0变为$#words
,或者是数组的最终元素的索引。这一行
join " ", $words[$i], $words[$i + 1], $words[$i + 2];
访问数组$words[$i]
的最后一个元素以及两个不存在的元素。
在这种情况下,与使用数组当前索引的任何循环一样,最简单的方法是迭代数组 indices 而不是内容。要使join
有效,您需要从零开始并在结束前停止两个元素,因此0 .. $#words-2
。
使用数组 slice 来选择trigram的三个元素也更简洁,并使用将数组插入字符串的事实,如"@array"
中所做的那样与join ' ', @array
相同。 (更准确地说,它join $", @array
,$"
默认设置为单个空格。)
我建议这个修复。在每个Perl程序的开头,use strict
和use warnings
是必需的,您应该尽可能晚地使用my
声明所有变量。
use strict;
use warnings;
my %hash;
while (<>) {
my @words = split;
my @trigrams;
for my $i (0 .. $#words - 2) {
my $word = $words[$i];
++$hash{$word};
$trigrams[$i] = "@words[$i,$i+1,$i+2]";
print "$word\n";
}
}
<强>更新强>
如果你不是太简洁,你可能会喜欢这个
use strict;
use warnings;
my %hash;
while (<>) {
my @words = split;
my @trigrams = map "@words[$_,$_+1,$_+2]", 0 .. $#words-2;
}