sub sieve { my @pats = UNIVERSAL::isa($_[0], 'Regexp') ? @_ : map(qr/$_/, @_); sub { my %slots; $slots{$_} = [] for @pats, ""; my $cref = UNIVERSAL::isa($_[0], 'CODE') && shift; ITEM: for (@_) { my $k = $cref ? $cref->() : $_; for my $p (@pats) { push(@{ $slots{$p} }, $_), next ITEM if $k =~ /$p/; } push @{ $slots{""} }, $_; } return map @$_, @slots{@pats, ""}; } } my %tapes = (...); my $c5p5 = sieve(qr/-C5$/, qr/-P5$/); my @sorted_keys = $c5p5->(sub { $tapes{$_} }, keys %tapes);