Perl: if ( element in list )

后端 未结 10 555
栀梦
栀梦 2021-01-30 06:05

I\'m looking for presence of an element in a list.

In Python there is an in keyword and I would do something like:

if element in list:
            


        
相关标签:
10条回答
  • 2021-01-30 06:42
    if( $element ~~ @list ){
       do_task
    }
    

    ~~ is the "smart match operator", and does more than just list membership detection.

    0 讨论(0)
  • 2021-01-30 06:42

    Probably Perl6::Junction is the clearest way to do. No XS dependencies, no mess and no new perl version required.

    use Perl6::Junction qw/ any /;
    
    if (any(@grant) eq 'su') {
        ...
    }
    
    0 讨论(0)
  • 2021-01-30 06:45

    List::Util::first

    $foo = first { ($_ && $_ eq "value" } @list;    # first defined value in @list
    

    Or for hand-rolling types:

    my $is_in_list = 0;
    foreach my $elem (@list) {
        if ($elem && $elem eq $value_to_find) {
            $is_in_list = 1;
            last;
        }
    }
    if ($is_in_list) {
       ...
    

    A slightly different version MIGHT be somewhat faster on very long lists:

    my $is_in_list = 0;
    for (my $i = 0; i < scalar(@list); ++$i) {
        if ($list[i] && $list[i] eq $value_to_find) {
            $is_in_list = 1;
            last;
        }
    }
    if ($is_in_list) {
       ...
    
    0 讨论(0)
  • 2021-01-30 06:51

    If you plan to do this many times, you can trade-off space for lookup time:

    #!/usr/bin/perl
    
    use strict; use warnings;
    
    my @array = qw( one ten twenty one );
    my %lookup = map { $_ => undef } @array;
    
    for my $element ( qw( one two three ) ) {
        if ( exists $lookup{ $element }) {
            print "$element\n";
        }
    }
    

    assuming that the number of times the element appears in @array is not important and the contents of @array are simple scalars.

    0 讨论(0)
  • 2021-01-30 06:52

    TIMTOWTDI

    sub is (&@) {
      my $test = shift;
      $test->() and return 1 for @_;
      0
    }
    
    sub in (@) {@_}
    
    if( is {$_ eq "a"} in qw(d c b a) ) {
      print "Welcome in perl!\n";
    }
    
    0 讨论(0)
  • 2021-01-30 06:54

    You can accomplish a similar enough syntax in Perl if you do some Autoload hacking.

    Create a small package to handle the autoload:

    package Autoloader;
    use strict;
    use warnings;
    
    our $AUTOLOAD;
    
    sub AUTOLOAD {
        my $self     = shift;
        my ($method) = (split(/::/, $AUTOLOAD))[-1];
    
        die "Object does not contain method '$method'" if not ref $self->{$method} eq 'CODE';
    
        goto &{$self->{$method}};
    }
    
    1;
    

    Then your other package or main script will contain a subroutine that returns the blessed object which gets handled by Autoload when its method attempts to be called.

    sub element {
        my $elem = shift;
    
        my $sub = {
            in => sub {
                return if not $_[0];
    
                # you could also implement this as any of the other suggested grep/first/any solutions already posted.
                my %hash; @hash{@_} = ();
                return (exists $hash{$elem}) ? 1 : ();
            }
        };
    
        bless($sub, 'Autoloader');
    }
    

    This leaves you with usage looking like:

    doTask if element('something')->in(@array);
    

    If you reorganize the closure and its arguments, you can switch the syntax around the other way to make it look like this, which is a bit closer to the autobox style:

    doTask if search(@array)->contains('something');
    

    function to do that:

    sub search {
        my @arr = @_;
    
        my $sub = {
            contains => sub {
                my $elem = shift or return;
                my %hash; @hash{@arr} = ();
                return (exists $hash{$elem}) ? 1 : ();
            }
        };
    
        bless($sub, 'Autoloader');
    }
    
    0 讨论(0)
提交回复
热议问题