尝试运行下面的代码时,我从Perl收到以下错误
Use of uninitialized value within @words in concatenation (.) or string...
Run Code Online (Sandbox Code Playgroud)
它引用了我尝试创建由三个单词序列组成的数组的行(以该行开头的行$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++;
}
}
Run Code Online (Sandbox Code Playgroud)
所有发生的事情都是你从阵列的末端掉下来@words.您正在为每个元素执行循环@words,因此值$i从0到$#words,或者是数组的最后一个元素的索引.所以行
join " ", $words[$i], $words[$i + 1], $words[$i + 2];
Run Code Online (Sandbox Code Playgroud)
访问数组的最后一个元素$words[$i]和两个不存在的元素.
在这种情况下,与使用数组当前索引的任何循环一样,最简单的方法是迭代数组索引而不是内容.对于join是有效的,你需要从零开始,并在年底前两个元素停止,所以0 .. $#words-2.
使用数组切片为trigram选择三个元素也更简洁,并使用将数组插入字符串的事实,如同"@array",将执行相同的操作join ' ', @array.(更确切地说,它确实如此join $", @array,并且$"默认设置为单个空格.)
我建议这个修复.这是必要的,以use strict和use warnings在每一个Perl程序开始时,你应该使用声明所有的变量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";
}
}
Run Code Online (Sandbox Code Playgroud)
更新
如果它不是太简洁你可能会喜欢这个
use strict;
use warnings;
my %hash;
while (<>) {
my @words = split;
my @trigrams = map "@words[$_,$_+1,$_+2]", 0 .. $#words-2;
}
Run Code Online (Sandbox Code Playgroud)