如何在Perl中从结构数组中删除重复项?

时间:2018-12-02 21:31:34

标签: perl

我在文本文件中有数据。这只是名称和要点。我需要删除重复的名称并计算平均分。我创建了一个结构,并将文件读入结构数组。现在如何处理数组中的数据?我该如何让一个以上档案中的人得分并计算平均值? Perl对我来说是新语言,我不太了解语法。我的代码:

use Class::Struct; 
use warnings;
use strict;   

struct Person => {
    name => '$',
    points => '$'};


my $filename = 'data.txt';
open(my $fh, '<:encoding(UTF-8)', $filename)
    or die "Could not open file\n";

my @resultArray;
my @name;
my @name2;
my @grade2;
my @grade;
my @nameArray;
my @gradeArray;

my $person = Person->new();


while (my $row = <$fh>) {
    chomp $row;
    (@name, @grade) = split("\t", $row);
    push(@nameArray, @name);
    #($person->name, $person->points) = split("\t", $row);  
    #push(@nameArray, @name);

}
foreach(@nameArray) {
my @seperated = split(' ', $_);
$person->name($seperated[0]);
$person->points($seperated[1]);
}

print($person->points);

1 个答案:

答案 0 :(得分:2)

要为每个人创建一个数组条目,您需要在循环内为每个人创建一个新对象。读取数据后,您必须对其进行后处理以建立重复项并删除除一项以外的所有项。

效率低下,需要额外调用构造函数和析构函数以及从数组中删除。

因此,我建议改为将数据读入哈希,这样您就可以在处理过程中处理重复项。然后用struct个对象填充数组以进行进一步的工作。

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

use Class::Struct; 

struct Person => { name => '$', points => '$' };

my @people; 

PREPARE_DATA: {    
    my (%people, %cnt);

    while (<DATA>) {
        my ($name, $pts) = split;
        if (exists $people{$name}) {
            $people{$name} += $pts;
            ++$cnt{$name};
        }   
        else { 
            $people{$name} = $pts;
        }   
    }

    foreach my $name (keys %cnt) { 
        $people{$name} /= $cnt{$name}+1;
    }    

    # Now populate an array with objects
    foreach my $name (sort keys %people) {    
        push @people, Person->new(name => $name, points => $people{$name});
    }
};

for my $p (@people) {
    say $p->name, ' --> ', $p->points;
}

__DATA__
Joe 12
John 20
Joe 24
John 40
Joe 36
Matt 15

我将所有处理放入一个块(我将其命名为PREPARE_DATA)中,以限制使用的辅助变量的范围;在该块之后,仅存在所需的@people

使用__DATA__部分提供了数据,因此可以很容易地看到此处使用的所有数据。

没有必要进行仅存伪造物数量的存在性检验。一个人可以加分,增加每个人的分数,然后再除以他们的分数。仅检查重复项会更有效,更重要的是,它更易于检查其他类型的属性。