in reply to multiple matching in arrays

Depending on the complexity of match_names (and the size of the arrays being tested) you could also use a regular expression to find the matches.

But for clarity you are probably best off with the nested loops and hash approach offered by rodion

sub test_regex { my @array1 = ( "test", "test2", "test2", "test3", "test4", "test4" + ); my @array2 = ( "test", "test", "test2.1", "test4.1", "test4.2", "t +est4.3" ); # Create a list of the items in array 1 separated by | # The reverse sort is used to keep the longer names to the front o +f # the list, in order to avoid matching 'test' when we could match +'test4' my $match_array1 = join('|',reverse sort @array1); # Using the 'x' option with regular expressions helps readability, + # even in simple cases like this my $regex = qr{ ^ ($match_array1) }x; my %found_one = (); foreach my $item2 (@array2) { next unless defined $item2; if ($item2 =~ /$regex/) { $found_one{$1}++; } } return keys %found_one; }
use strict; use warnings; use Benchmark qw(cmpthese); if (0) { print "regex: $_\n" for test_regex(); print "loop: $_\n" for test_loop(); exit; } cmpthese(1000,{ loop => \&test_loop, regex => \&test_regex, }); sub test_regex { my @array1 = ( "test", "test2", "test2", "test3", "test4", "test4" + ); my @array2 = ( "test", "test", "test2.1", "test4.1", "test4.2", "t +est4.3" ); # Create a list of the items in array 1 separated by | # The reverse sort is used to keep the longer names to the front o +f # the list, in order to avoid matching 'test' when we could match +'test4' my $match_array1 = join('|',reverse sort @array1); # Using the 'x' option with regular expressions helps readability, + # even in simple cases like this my $regex = qr{ ^ ($match_array1) }x; my %found_one = (); foreach my $item2 (@array2) { next unless defined $item2; if ($item2 =~ /$regex/) { $found_one{$1}++; } } return keys %found_one; } sub test_loop { my @array1 = ( "test", "test2", "test2", "test3", "test4", "test4" + ); my @array2 = ( "test", "test", "test2.1", "test4.1", "test4.2", "t +est4.3" ); my %found_one = (); foreach my $item1 (@array1) { foreach my $item2 (@array2) { next unless defined $item2; if (match_names($item1, $item2)) { $found_one{$item1}++; last; } } } return keys %found_one; } sub match_names { my ($x,$y) = @_; return 1 if ($y =~ /$x/); return; }
The results on my machine are:
Rate loop regex loop 1136/s -- -60% regex 2857/s 151% --