my %h1 = $csv1->csv_to_hash; # with $csv1 the smallest file my %temp; while (my $line = $csv2->next) { my $key = $line->key; # Ignore lines that don't also exist in h1 # That's way less data to build into the second hash next unless exists $h1{$key}; my $value = $line->value; $temp{ $key } = [ $h1{$key}, $value ]; } %h1 = (); # Free the data from %h1, the matching pairs are all in %temp anyway my %out; while (my $line = $csv3->next) { my $key = $line->key; # As before, ignore non relevant keys next unless exists $temp{$key}; # We make a copy of the array ref from %temp # This means that technically modifying it also changes the content of %temp # But it will be deleted anyway my $values_array = $temp{$key}; my $value = $line->value; push @$values_array, $value; # Add the values into a brand new hash # So that it contains only the needed keys $out{$key} = $values_array; } %temp = (); # The important keys have been copied to %out;