1

I'd like to see if a hash contains any of a list of keys. Currently I have:

if (grep {$me_hash{$_}} @me_list){
    ...

but I figure it's inefficient because it doesn't quit on the first match. Is there a better, more idiomatic way to do it?

kthxbi

2 Answers 2

5

You can use List::MoreUtils's any

use List::MoreUtils qw(any);
if (any { $me_hash{$_} } @me_list) {

Which presumably short circuits on the first match. This function is rather simple, looking like this:

sub any (&@) {
    my $f = shift;
    foreach ( @_ ) {
        return YES if $f->();
    }
    return NO;
}

Where YES and NO are defined as

use constant YES => ! 0;
use constant NO  => ! 1;

Meaning you can swing your own version of this with something like

sub is_in {
    my ($href, @list) = @_;
    for (@list) {
        return 1 if $href->{$_};
    }
    return 0;
}

Note that the statement you are using $me_hash{$_} can return false for values you might not consider false, such as the empty string, or zero 0.

Sign up to request clarification or add additional context in comments.

1 Comment

Note that all of @me_list is placed on the stack, but this should be very fast as it does not involve copying more than pointers.
1

List::Util unlike List::MoreUtils is core module,

use List::Util qw(first);
if (defined first {$me_hash{$_}} @me_list) { .. }

and if you don't want to use any of external modules,

my $any = sub{ $me_hash{$_} and return 1 for @_; 0 }->(@me_list);
if ($any) { .. }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.