Perl Очистка данных: как мне составить список не дублированных имен и сохранить все эти маленькие списки в ха sh? - PullRequest
1 голос
/ 12 апреля 2020

Я новичок в Perl, и мне нужно почистить данные. Просто для быстрого подсчета того, что я делаю, у меня есть список идентификаторов (Horse_ID), каждый идентификатор для одной лошади. Лошади соревновались в нескольких гонках, поэтому их удостоверение напечатано в нескольких строках (каждая строка соответствует одному соревнованию). Для каждой гонки они соревновались с разными тренерами (или нет).

Исходные данные, чтобы точно показать, с чем я имею дело

Я хотел бы сохранить в ha sh имена разных дрессировщиков для каждой лошади и количество разных дрессировщиков для каждой лошади.

После того, как я проконсультировался по поводу переполнения стека, я создал код. Но мой код печатает только имя найденного тренера и неправильное количество тренеров (иногда 0, что ничего не значит). Я не могу найти ошибку ... Это мой код:

if (($coach =~ /\w+/) && ($Horse_ID ne '')) { 
    if (($trainerhash -> {$Horse_ID} -> {trainerinfo}) && ($trainerhash -> {$Horse_ID} -> {trainerinfo} !~ /$Horse_ID/)) {
        $trainerhash -> {$Horse_ID} -> {trainerinfo} .= "\t$coach"; 
        my @coach = split (/\s/, $coach);
         $numtrainers = $#coach+1;

    }
    elsif (!$trainerhash -> {$Horse_ID} -> {trainerinfo}) {
        $trainerhash -> {$Horse_ID} -> {trainerinfo} = "$coach";
    }

}

# Trainer hash - Number of trainers & trainer names
$trainerhash -> {$Horse_ID} -> {trainerinfo} = "$numtrainers\t$coach"; 

Если у кого-то есть идея, было бы здорово ... Я уже пробовал использовать для l oop, но результат тот же.

Входные данные

Horse_ID    name    date    localisation    distance race_kategory  rider   rider_weight    coach
1   Abakus  03/11/2018  Warszawa    1400    I   V_Popov 58  S_Vasyutov  6
1   Abakus  09/09/2018  Warszawa    1800    I   V_Popov 58  S_Vasyutov  5
1   Abakus  12/08/2018  Warszawa    1800    I   A_Kabarov   58  S_Vasyutov  x
1   Abakus  30/06/2018  Warszawa    1800    I   V_Popov 58  S_Vasyutov  8
1   Abakus  09/06/2018  Warszawa    1600    II  V_Popov 58  S_Vasyutov  1
2   Abbas   19/11/2017  Warszawa    2000    I   S_Vasyutov  58  S_Vasyutov  3
2   Abbas   28/10/2017  Warszawa    1400    II  P_Naoniechnyi   58  S_Vasyutov x
2   Abbas   08/10/2017  Warszawa    1400    II  P_Naoniechnyi   58  S_Vasyutov x

Заранее благодарю за помощь,

Ответы [ 2 ]

1 голос
/ 12 апреля 2020

Хеши отлично подходят для поиска дубликатов или группировки элементов. Мы собираемся использовать их для группировки лошадей и удаления дублирующих тренеров.

Количество тренеров - это просто количество элементов в массиве тренеров, поэтому нам не нужно хранить их где-либо.

use strict;
use warnings;
use feature qw( say );

my %trainers_by_horse;
if (defined( $_ = <DATA> )) {
   chomp;
   my @headers = split /\t/;
   while (<DATA>) {
      chomp;
      my %fields;
      @fields{@headers} = split /\t/;
      my $horse_id = $fields{Horse_ID};
      my $trainer  = $fields{coach};
      ++$trainers_by_horse{$horse_id}{$trainer};
   }
}

# Convert from
#    $trainers_by_horse{$horse_id}{$trainer} = $num_rows;
# to
#    $trainers_by_horse{$horse_id} = \@trainers;

for my $trainers (values(%trainers_by_horse)) {
   $trainers = [ sort keys(%$trainers) ];
}

for my $horse_id (sort { $a <=> $b } keys(%trainers_by_horse)) {
   my $trainers     = $trainers_by_horse{$horse_id};
   my $num_trainers = @$trainers;

   say(join("\t", $horse_id, $num_trainers, join(",", @$trainers)));
}

(я предположил, что ваши данные были разделены табуляцией. Если они разделены только пробелами, просто удалите оба /\t/.)

Например,

Horse_ID    name    date    localisation    distance    race_kategory   rider   rider_weight    coach
1   Abakus  03/11/2018  Warszawa    1400    I   V_Popov 58  S_Vasyutov  6
1   Abakus  09/09/2018  Warszawa    1800    I   V_Popov 58  S_Vasyutov  5
1   Abakus  12/08/2018  Warszawa    1800    I   A_Kabarov   58  S_Vasyutov  x
1   Abakus  30/06/2018  Warszawa    1800    I   V_Popov 58  S_Vasyutov  8
1   Abakus  09/06/2018  Warszawa    1600    II  V_Popov 58  S_Vasyutov  1
2   Abbas   19/11/2017  Warszawa    2000    I   S_Vasyutov  58  S_Vasyutov  3
2   Abbas   28/10/2017  Warszawa    1400    II  P_Naoniechnyi   58  S_Vasyutov  x
2   Abbas   08/10/2017  Warszawa    1400    II  P_Naoniechnyi   58  S_Vasyutov  x
2   Abbas   30/07/2017  Warszawa    1800    II  P_Naoniechnyi   58  S_Vasyutov  x
3   Abdank  19/05/2018  Warszawa    1600    II  S_Vasyutov  58  S_Vasyutov  3
4   Adlina  07/09/2008  Wrocaw  1700    II  D_Szope 56  J_Pochwatka 9
4   Adlina  07/09/2008  Wrocaw  1800    II  D_Szope 58  S_Vasyutov  6

производит

1   1   S_Vasyutov
2   1   S_Vasyutov
3   1   S_Vasyutov
4   2   J_Pochwatka,S_Vasyutov
0 голосов
/ 12 апреля 2020

Пожалуйста, посмотрите фрагмент кода, как

ввод читается

разбит на поля

хранится в %race га sh

сформированные %trainer га sh с интересующей информацией

выходные данные %trainer га sh данные (нет требуемого формата вывода, предлагаемого OP)

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

use Data::Dumper;

my $debug = 0;

my($header,@fields);
my %trainer;

$header = <DATA>;
chomp $header;

@fields = split ' ', $header;

while( <DATA> ) {
    chomp;
    next if /^$/;           # skip empty lines
    my %race;
    @race{@fields} = split;
    push @{ $trainer{$race{Horse_ID}}{trainerinfo} }, $race{coach} 
        if not grep { /$race{coach}/ } @{ $trainer{$race{Horse_ID}}{trainerinfo} };
}

say Dumper(\%trainer) if $debug;

say '
Horse   Count   Trainers
----------------------------';
for ( sort keys %trainer ) {
    printf "%d\t%d\t%s\n",
            $_, 
            scalar @{$trainer{$_}{trainerinfo}},
            join(', ', @{$trainer{$_}{trainerinfo}});
}

__DATA__
Horse_ID    name    date    localisation    distance race_kategory  rider   rider_weight    coach
1   Abakus  03/11/2018  Warszawa    1400    I   V_Popov 58  S_Vasyutov  6
1   Abakus  09/09/2018  Warszawa    1800    I   V_Popov 58  S_Vasyutov  5
1   Abakus  12/08/2018  Warszawa    1800    I   A_Kabarov   58  S_Vasyutov  x
1   Abakus  30/06/2018  Warszawa    1800    I   V_Popov 58  S_Vasyutov  8
1   Abakus  09/06/2018  Warszawa    1600    II  V_Popov 58  S_Vasyutov  1
2   Abbas   19/11/2017  Warszawa    2000    I   S_Vasyutov  58  S_Vasyutov  3
2   Abbas   28/10/2017  Warszawa    1400    II  P_Naoniechnyi   58  S_Vasyutov x
2   Abbas   08/10/2017  Warszawa    1400    II  P_Naoniechnyi   58  S_Vasyutov x
2   Abbas   30/07/2017  Warszawa    1800    II  P_Naoniechnyi   58  S_Vasyutov x
3   Abdank  19/05/2018  Warszawa    1600    II  S_Vasyutov  58  S_Vasyutov  3
4   Adlina  07/09/2008  Wrocaw  1700    II  D_Szope 56  J_Pochwatka 9
4   Adlina  07/09/2008  Wrocaw  1800    II  D_Szope 58  S_Vasyutov  6

Выходные данные

Horse   Count   Trainers
----------------------------
1       1       S_Vasyutov
2       1       S_Vasyutov
3       1       S_Vasyutov
4       2       J_Pochwatka, S_Vasyutov

ПРИМЕЧАНИЕ:

  • укажите имя ха sh %horse, чтобы сохранить список тренеров / дрессировщиков для лошади
  • укажите имя ха sh %trainer, чтобы вести список обученных лошадей тренером
...