use strict; use warnings; use Data::Dumper; $Data::Dumper::Indent = 1; my @data = ( {season => 1, ep => 1, title => 'Hellmouth' }, {season => 1, ep => 2, title => 'Harvest' }, {season => 1, ep => 3, title => 'Witch' }, {season => 1, ep => 4, title => 'Teacher' }, {season => 1, ep => 5, title => 'First Date'}, {season => 2, ep => 13, title => 'Bad' }, {season => 2, ep => 14, title => 'Assembly' }, {season => 2, ep => 15, title => 'School' } ); my @appearances; my $curr_season = 0; foreach my $data (@data) { my $record = { title => $data->{title} }; if ($data->{season} != $curr_season) { push @appearances => { season => $data->{season}, eps => [ $record ] }; $curr_season = $data->{season}; } else { push @{$appearances[-1]{eps}} => $record; } } print Dumper \@appearances;