use warnings; use strict; use Data::Dump qw(pp); my %hash; while () { chomp; next if /\A\s*\z/; my @pieces = split ',' => $_; for my $idx (3..4) { push @{ $hash {$pieces[0]} {$pieces[1]} {$pieces[2]} [$idx-3] }, $pieces[$idx]; } } pp %hash; __DATA__ Joe,A,1,85,90 Joe,A,1,80,99 Joe,A,2,50,70 Joe,A,2,60,65 Joe,A,2,87,89 Joe,B,1,82,92 Joe,B,3,30,51 Rob,A,1,64,77 Rob,B,2,20,32