如何统计数组中同词形行数并在新数组插入计数器(Perl)
解决Perl统计词形出现次数的问题
我来帮你搞定这个计数需求!因为你的输入文件已经是排序后的,相同词形都是连续出现的,咱们可以利用这个特点来高效统计次数,不用额外的哈希表(当然用哈希也能做,但连续的情况直接遍历更简单)。
核心思路
- 初始化计数器、当前词形、当前原型三个变量,用来跟踪当前正在统计的词形组
- 遍历每一行,拆分出词形和原型
- 遇到和当前词形相同的行,计数器+1;遇到不同的,就把之前统计好的结果写入输出数组,然后重置计数器和当前跟踪的变量
- 遍历结束后,别忘了把最后一组的统计结果也写入输出数组(循环里不会处理最后一组)
修改后的完整代码
# 初始化变量 my $count = 1; my ($current_form, $current_lemma); my @lines_out; foreach my $line (@lines) { # 先把当前行拆分成词形和原型(比你原来的正则更准确,避免匹配到中间的WORD) if ($line =~ /^(.+)WORD(.+)$/) { my $form = lc $1; # 转小写统一比较,避免大小写差异导致统计错误 my $lemma = $2; # 处理第一行的情况:初始化当前跟踪的变量 if (!defined $current_form) { $current_form = $form; $current_lemma = $lemma; next; } # 如果当前词形和正在跟踪的词形相同,计数器加1 if ($form eq $current_form) { $count++; } else { # 不同的话,把之前的统计结果拼好加入输出数组 push @lines_out, "$count $current_formWORD$current_lemma"; # 重置计数器和跟踪变量 $count = 1; $current_form = $form; $current_lemma = $lemma; } } else { # 处理格式不符合的行(可选,根据你的需求调整) warn "Skipping invalid line: $line"; } } # 别忘了把最后一组的统计结果加入输出数组 if (defined $current_form) { push @lines_out, "$count $current_formWORD$current_lemma"; }
关键细节说明
- 计数器的位置:
$count要在循环外面初始化(值为1,因为每一行至少出现一次),每次遇到相同词形就递增,遇到不同词形时重置为1。 - 插入统计结果到数组:当检测到词形变化时,把
次数 + 词形 + WORD + 原型拼接成新行,push到@lines_out里;循环结束后必须处理最后一组,否则会漏掉。 - 词形比较:用
lc转成小写统一比较,避免大小写差异导致统计错误(比如"Run"和"run"会被当成同一个词形)。
示例演示
假设你的输入@lines是:
runWORDrun runWORDrun RunningWORDrun jumpWORDjump
处理后@lines_out会变成:
2 runWORDrun 1 RunningWORDrun 1 jumpWORDjump
内容的提问来源于stack exchange,提问作者fruit_alchemist
相关产品推荐
相关产品推荐

