Как удалить дубликаты из массива структуры в Perl? - PullRequest
0 голосов
/ 03 декабря 2018

У меня есть данные в текстовом файле.Это только имя и очки.Мне нужно удалить дубликаты имен и посчитать среднее количество баллов.Я создал структуру и прочитал файл в массив массива.Теперь, как я могу манипулировать данными в массиве?Как я могу взять людей, которые находятся в файле более одного раза, очки и подсчитать среднее?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 голосов
/ 03 декабря 2018

Чтобы иметь запись в массиве для каждого человека, вам нужно создать новый объект для каждого внутри цикла.После прочтения данных вам придется постобработать их, чтобы установить дубликаты и удалить все записи, кроме одной.

Это неэффективно, с дополнительными вызовами конструктора и деструктора и удалениями из массива.

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

Проверка на существование, посредством чеговедется подсчет только дуплей, не обязательно.Можно добавить очки и увеличить количество для каждого человека, а затем разделить все на их счет.Проверка только дупсов немного более эффективна и, что более важно, более удобна для проверки других типов свойств.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...