如何在 Perl 中将文件读入数组但正确处理重复项?

How do I read a file into an array in Perl but correctly handle duplicates?

如何将文件读入数组,但正确处理重复项?

我有一个包含两列的文件,一个名称和一个数字。最终名称会重复,数字可能不同也可能不同。

Rita,13
Sue,11
Bob,01
Too,05
Rita,13
Sue,07
Bob,02
Too,05

我需要将这些行读入一个数组,这不是问题,但以某种方式重新填充它们,以便任何重复的名称都将其值推送到正确的行,这比较棘手。至少对我来说。

所以上面应该创建类似

的东西
Rita,13,13
Sue,11,07
Bob,01,02
Too,05,05

大约有 3000 个名称和大约 600,000 行要处理。 (想法是突出显示哪些名称是稳定的,哪些名称具有变化的值)。

速度并不重要。这将是 运行 大约每周一次。

因为每一行最终都会有多个条目,而每行的第二个条目并不重要(我只需要阅读它并将其填充到新列表),我想我不需要在这里使用散列,我应该只用某种形式的 if 存在(或不存在)遍历输入文件。我是对的还是散列会有好处?

我在 Windows 上使用 Strawberry Perl V5.32.1。

编辑 - 感谢样品,一切都很好。

由于输出发生变化,输入文件现在有必须保留的额外列。

所以现在看起来像

12,Rita,1,4,13 
2,Sue,0,1,11 
5,Bob,12,5,01 
7,Too,1,4,05 
12,Rita,1,4,13 
2,Sue,0,1,07 
5,Bob,12,5,02 
7,Too,1,4,05 

输出类似,因为只有最后一列会改变

12,Rita,1,4,13,13 
2,Sue,0,1,11,07 
5,Bob,12,5,01,02 
7,Too,1,4,05,05 

额外的列不会改变,但必须存在。使用数组并提取第 2 和第 5 列来创建它,或者更改前 4 列的分隔符以使第一列成为唯一键是否仍然有意义?这感觉很脏,但可以工作...

单线

perl -F, -lane '$h{ $F[0] } .= ",$F[1]"; END {print $_, $h{$_} for keys %h}' -- file

作为脚本:

#!/usr/bin/perl
use warnings;
use strict;

my %h;
while (<>) {
    chomp;
    my ($name, $number) = split /,/;
    $h{$name} .= ",$number";
}
for my $name (keys %h) {
    print $name, $h{$name}, "\n";
}

使用以 用户名 为键的散列和 id 存储在一个数组中使这个任务很容易实现。

请调查以下代码段。

use warnings;
use feature 'say';

my $data;

while( <DATA> ) {
    chomp;
    my($name,$id) = split /,/;
    push @{$data->{$name}}, $id;
}

say join(',',$_,@{$data->{$_}}) for sort keys %$data;

exit 0;

__DATA__
Rita,13
Sue,11
Bob,01
Too,05
Rita,13
Sue,07
Bob,02
Too,05

输出

Bob,01,02
Rita,13,13
Sue,11,07
Too,05,05

您的问题的基本解决方案已给出,但忽略了两件事:1) 名称的原始顺序不能用散列保留,2) 如果任何一行有多个值,则丢弃附加值.所以我想到了这个:

use strict;
use warnings;
use feature 'say';

my %d;
my @keys;
while (<DATA>) {
    chomp;
    my ($key, @val) = split /,/, $_;            # use array to store multiple values
    push @keys, $key if not defined $d{$key};   # preserve original order of lines
    push @{ $d{$key} }, @val;                   # store values
}

say join ",", $_, @{ $d{$_} } for @keys;        # print lines in original order

__DATA__
Rita,13
Sue,11
Bob,01,23
Too,05
Rita,13
Sue,07
Bob,02
Too,05

输出:

Rita,13,13
Sue,11,07
Bob,01,23,02
Too,05,05