Следующий код читает данные, разделяется на поля и строит га sh с ключами персона , позиция , роль .
Один раз ха sh сформировал вывод данных на консоль в соответствии с клавишами га sh.
use strict;
use warnings;
use feature 'say';
my %hash;
my %seen;
my @header = split ',', <DATA>;
chomp @header;
while(<DATA>) {
next if /^$/;
chomp;
my %data;
@data{@header} = split ',';
push @{$hash{person}}, \%data;
push @{$hash{Position}{$data{Position}}}, "$data{Last} $data{First}";
if( ! $seen{$data{Position}} ) {
$seen{$data{Position}} = 1;
push @{$hash{Role}}, $data{Position};
}
}
say "--- My list ----\n";
my $count = 0;
for my $person ( @{$hash{person}} ) {
$count++;
say "-> Person: $count";
say "-> Name: $person->{First} $person->{Last}";
say "-> Role: $person->{Position}\n";
}
say "---- Groups ----\n";
while( my($p,$m) = each %{$hash{Position}} ) {
say "-> $p: ";
say '-> Members: ' . join(', ',@{$m}) . "\n";
}
say "---- Roles ----";
say '-> ' . join(', ',@{$hash{Role}});
__DATA__
First,Last,Position
John,Doe,Developer
Mary,Fox,Manager
Anna,Gulaby,Developer
Вывод
--- My list ----
-> Person: 1
-> Name: John Doe
-> Role: Developer
-> Person: 2
-> Name: Mary Fox
-> Role: Manager
-> Person: 3
-> Name: Anna Gulaby
-> Role: Developer
---- Groups ----
-> Manager:
-> Members: Fox Mary
-> Developer:
-> Members: Doe John, Gulaby Anna
---- Roles ----
-> Developer, Manager
ОП довел до моего сведения, что у него возникла проблема с код.
Обнаружена причина проблемы: входные данные eol в форме DOS \r\n
в системе Linux. В Linux для некоторых версий perl [v5.22.1] - chomp
удаляет только \n
и оставляет \r
, который остается частью ключа для Position \ r поля. Спасибо Шон за указание на это.
Было обнаружено, что не все версии perl сталкиваются с этой проблемой. Новое сообщение было инициировано для демонстрации проблемы.
Следующее исправление работает для Linux / Windows (не тестировалось на других платформах).
use strict;
use warnings;
use feature 'say';
my $debug = 0;
say "
Perl: $^V
OS: $^O
-------------------
" if $debug; # for debug purpose to show perl version and OS
my %hash;
my %seen;
my @header = split ',', <DATA>;
$header[2] = snip_eol($header[2]); # problem fix
while(<DATA>) {
next if /^\s*$/;
my $line = snip_eol($_); # problem fix
my %data;
@data{@header} = split ',',$line;
push @{$hash{person}}, \%data;
push @{$hash{Position}{$data{Position}}}, "$data{First} $data{Last}";
if( ! $seen{$data{Position}} ) {
$seen{$data{Position}} = 1;
push @{$hash{Role}}, $data{Position};
}
}
#say Dumper($hash{Position});
my $count = 0;
for my $person ( @{$hash{person}} ) {
$count++;
say "-> Name: $person->{First} $person->{Last}";
say "-> Role: $person->{Position}\n";
}
say "---- Groups ----\n";
while( my($p,$m) = each %{$hash{Position}} ) {
say "-> $p";
my $members = join(',',@{$m});
say "-> Members: $members\n";
}
say "---- Roles ----";
say '-> ' . join(', ',@{$hash{Role}});
sub snip_eol { # problem fix
my $data = shift;
#map{ say "$_ => " . ord } split '', $data if $debug;
$data =~ s/\r// if $^O eq 'linux';
chomp $data;
#map{ say "$_ => " . ord } split '', $data if $debug;
return $data;
}
__DATA__
First,Last,Position
John,Doe,Developer
Mary,Fox,Manager
Anna,Gulaby,Developer