my %seen; my @union = grep {! $seen{$_}++} @rows, @data; #### my %seen; @seen{@data, @rows} = (); @data = keys %seen; #### @data = uniq @data, @rows; #### use strict; use warnings; use Test::More; use Benchmark qw(cmpthese); use List::Util qw(uniq); my @first = (1 .. 1000); my @second = (300 .. 700); sub slice { my %seen; @seen{@{$_[0]}, @{$_[1]}} = (); return [keys %seen]; } sub listutil { return [uniq(@{$_[0]}, @{$_[1]})]; } sub seengrep { my %seen; return [grep {! $seen{$_}++} @{$_[0]}, @{$_[1]}]; } is_deeply [sort {$a <=> $b} @{slice( \@first, \@second)}], [sort {$a <=> $b} @{listutil(\@first, \@second)}], "They matched."; is_deeply [sort {$a <=> $b} @{listutil(\@first, \@second)}], [sort {$a <=> $b} @{seengrep(\@first, \@second)}], "They matched again."; done_testing(); cmpthese (-5, { slice => sub {my $f = slice (\@first, \@second)}, listutil => sub {my $f = listutil(\@first, \@second)}, seengrep => sub {my $f = seengrep(\@first, \@second)}, }); #### ok 1 - They matched. ok 2 - They matched again. 1..2 Rate seengrep slice listutil seengrep 3555/s -- -16% -17% slice 4233/s 19% -- -1% listutil 4297/s 21% 2% -- #### my @list_A = (1..1000); my @list_B = (1..1000); # Exhibit A: foreach my $element (@list_A, @list_B) { do_something($element); } # Exhibit B: foreach my $element_A (@list_A) { foreach my $element_B(@list_B) { do_something($element_A, $element_B); } } #### foreach my $row (@rows) { push @data, $row unless $row ~~ @data; } #### foreach my $row (@rows) { my $found = 0; foreach my $element (@data) { if ($row =~ m/\Q$element/) { $found = 1; last; } } push @data, $row if $found; } #### foreach my $element(@data, @rows) { $seen{$_} = (); }