use strict; use warnings; use Data::Dump qw/pp dd/; # --- input data my @sorted_data = ( { 'count_payment' => '', 'count_banking' => '31 (62.00)', 'name' => 'Parking Eye [LTD] One', }, { 'count_payment' => '10 (144.00)', 'count_banking' => '', 'name' => 'Parking Eye [LTD] Two', }, { 'count_payment' => '2 (80.42)', 'count_banking' => '', 'name' => 'Parking Eye [LTD] Three', }, { 'count_payment' => '', 'count_banking' => '4 (982.00)', 'name' => 'Parking Eye [LTD] Two', } ); # --- join elements into temporary hash by name my %by_name; my $order = 0; for my $record (@sorted_data) { my $name = $record->{name}; # create new hash only if $name unknown $by_name{$name} //= { hsh => { name => $name }, ord => $order++, # preserve original order }; # concat other elements for my $field ( keys %$record ) { next if $field eq 'name'; $by_name{$name}{hsh}{$field} .= $record->{$field}; } } # --- copy hash values by order (Schwartzian transform) my @new_sorted_data = map { $_->{hsh} } sort { $a->{ord} <=> $b->{ord} } values %by_name; # --- dump result pp \@new_sorted_data;