@common = qw|a an and at the to|; timethese(1000, { Odud => q{ my (@only, %r, %seen); foreach $r (@words){ $r{lc $r} = 1; } my @uniqwords = sort keys %r; foreach my $item (@uniqwords) { push(@only,$item) unless exists $seen{$item}; } my @newwords = @only; }, PMGurus => q{ my %seen; @seen{@common} = (1) x @common; my @newwords = sort grep !$seen{+lc}++, @words; }, btrott_OneLiner => q{ my %seen; @seen{@common} = (1) x @common; my @newwords = sort grep !$seen{$_=lc}++, @words; }, btrott_FirstPass => q{ my (%seen, %r); @seen{@common} = (1) x @common; for my $r (@words) { next if exists $seen{ lc $r }; $r{lc $r} = 1; } my @newwords = sort keys %r; }, visnu => q{ my %common; @common{@common} = (1) x @common; my @newwords = sort keys %{+{ map { !$common{$_ = lc $_} ? ($_, 1) : () } @words }}; }, }); Benchmark: timing 1000 iterations of Odud, PMGurus, btrott_FirstPass, btrott_OneLiner, visnu... Odud: 9 wallclock secs ( 9.61 usr + 0.00 sys = 9.61 CPU) PMGurus: 6 wallclock secs ( 5.40 usr + 0.00 sys = 5.40 CPU) btrott_FirstPass: 7 wallclock secs ( 7.07 usr + 0.00 sys = 7.07 CPU) btrott_OneLiner: 6 wallclock secs ( 5.73 usr + 0.00 sys = 5.73 CPU) visnu: 10 wallclock secs (10.29 usr + 0.00 sys = 10.29 CPU)