Perl实现:按姓名与出生年份查找文件中出生数最高/最低的州
解决思路与代码优化
首先,你已经完成了总人数统计的核心部分,接下来要实现“找出对应条件下出生人数最高/最低的州”,我们可以通过**哈希表(Hash)**来跟踪每个州的累计出生数,之后再从哈希表中筛选出极值对应的州。
先修正现有代码的几个小问题
- 变量声明语法错误:
my $year, my $gender;这种写法不符合Perl规范,多个变量声明可以用括号包裹,比如my ($year, $gender); - 文件句柄的使用:建议用词法文件句柄和三参数
open,比旧式的open(FILE, $file)更安全,还能自动抛出错误信息 split后的变量赋值顺序错误:根据你给出的CSV示例(假设是逗号分隔格式,比如406738,Pilar,1964,F,CA,8),拆分后的字段顺序应为序号,姓名,年份,性别,州,数量,你的赋值语句需要对应调整
完整实现代码
use 5.13.0; use warnings; use strict; my $file = "StateNames.csv"; # 安全打开文件,失败则直接报错退出 open my $fh, '<', $file or die "无法打开文件 $file: $!"; my $total_count = 0; # 哈希表:键为州名,值为该州的累计出生数 my %state_counts; while (my $line = <$fh>) { chomp $line; # 去掉行尾的换行符,避免干扰字段拆分 # 拆分CSV字段,严格对应顺序:序号、姓名、年份、性别、州、数量 my ($id, $name, $year, $gender, $state, $count) = split /,/, $line; # 精准匹配条件:姓名是Paul,年份是1982 if ($name eq 'Paul' && $year == 1982) { $total_count += $count; # 累加对应州的计数,若州名首次出现会自动初始化值为0 $state_counts{$state} += $count; } } close $fh; # 处理完文件后及时关闭句柄 # 处理无匹配结果的情况 if ($total_count == 0) { print "没有找到1982年出生的Paul,请重试。\n"; exit; } # 输出总人数 print "1982年出生的Paul总人数为:$total_count\n"; # 找出最高和最低出生数的州 if (%state_counts) { # 获取所有州的计数列表,排序后提取极值 my @counts = values %state_counts; my $max_count = (sort { $b <=> $a } @counts)[0]; my $min_count = (sort { $a <=> $b } @counts)[0]; # 收集所有达到最大值的州(避免多个州有相同极值的情况) my @max_states = grep { $state_counts{$_} == $max_count } keys %state_counts; # 收集所有达到最小值的州 my @min_states = grep { $state_counts{$_} == $min_count } keys %state_counts; print "\n出生人数最多的州:\n"; foreach my $state (@max_states) { print "$state: $max_count人\n"; } print "\n出生人数最少的州:\n"; foreach my $state (@min_states) { print "$state: $min_count人\n"; } } else { print "没有找到对应条件的州数据。\n"; }
关键部分解释
- 哈希表
%state_counts:用来存储每个州的累计出生数,每匹配到一条符合条件的记录,就把该州的计数加上对应数值,首次出现的州会自动初始化值为0 - 筛选极值:通过
sort对计数列表排序后拿到最大值和最小值,再用grep找出所有对应计数的州,避免遗漏多个州有相同极值的情况 - 代码健壮性:加入了文件打开失败的报错、无匹配结果的处理,以及及时关闭文件句柄的操作,避免资源泄漏
内容的提问来源于stack exchange,提问作者elaird
相关产品推荐
相关产品推荐

