Чтобы иметь запись в массиве для каждого человека, вам нужно создать новый объект для каждого внутри цикла.После прочтения данных вам придется постобработать их, чтобы установить дубликаты и удалить все записи, кроме одной.
Это неэффективно, с дополнительными вызовами конструктора и деструктора и удалениями из массива.
Таким образом, я бы предложил вместо этого считывать данные в хеш, таким образом вы также можете обрабатыватьдублирует, как вы идете.Затем заполните массив 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__
, так что все данные, используемые здесь, легко видны.
Проверка на существование, посредством чеговедется подсчет только дуплей, не обязательно.Можно добавить очки и увеличить количество для каждого человека, а затем разделить все на их счет.Проверка только дупсов немного более эффективна и, что более важно, более удобна для проверки других типов свойств.