How do I search a Perl array for a matching string?

后端 未结 7 1679
一向
一向 2020-12-04 15:37

What is the smartest way of searching through an array of strings for a matching string in Perl?

One caveat, I would like the search to be case-insensitive

s

相关标签:
7条回答
  • 2020-12-04 16:07
    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    use Data::Dumper;
    
    my @bar = qw(aaa bbb);
    my @foo = grep {/aAa/i} @bar;
    
    print Dumper \@foo;
    
    0 讨论(0)
  • 2020-12-04 16:10

    Perl string match can also be used for a simple yes/no.

    my @foo=("hello", "world", "foo", "bar");
    
    if ("@foo" =~ /\bhello\b/){
        print "found";
    }
    else{
        print "not found";
    }
    
    0 讨论(0)
  • 2020-12-04 16:20

    Perl 5.10+ contains the 'smart-match' operator ~~, which returns true if a certain element is contained in an array or hash, and false if it doesn't (see perlfaq4):

    The nice thing is that it also supports regexes, meaning that your case-insensitive requirement can easily be taken care of:

    use strict;
    use warnings;
    use 5.010;
    
    my @array  = qw/aaa bbb/;
    my $wanted = 'aAa';
    
    say "'$wanted' matches!" if /$wanted/i ~~ @array;   # Prints "'aAa' matches!"
    
    0 讨论(0)
  • 2020-12-04 16:23

    For just a boolean match result or for a count of occurrences, you could use:

    use 5.014; use strict; use warnings;
    my @foo=('hello', 'world', 'foo', 'bar', 'hello world', 'HeLlo');
    my $patterns=join(',',@foo);
    for my $str (qw(quux world hello hEllO)) {
        my $count=map {m/^$str$/i} @foo;
        if ($count) {
            print "I found '$str' $count time(s) in '$patterns'\n";
        } else {
            print "I could not find '$str' in the pattern list\n"
        };
    }
    

    Output:

    I could not find 'quux' in the pattern list
    I found 'world' 1 time(s) in 'hello,world,foo,bar,hello world,HeLlo'
    I found 'hello' 2 time(s) in 'hello,world,foo,bar,hello world,HeLlo'
    I found 'hEllO' 2 time(s) in 'hello,world,foo,bar,hello world,HeLlo'
    

    Does not require to use a module.
    Of course it's less "expandable" and versatile as some code above.
    I use this for interactive user answers to match against a predefined set of case unsensitive answers.

    0 讨论(0)
  • 2020-12-04 16:26

    I guess

    @foo = ("aAa", "bbb");
    @bar = grep(/^aaa/i, @foo);
    print join ",",@bar;
    

    would do the trick.

    0 讨论(0)
  • 2020-12-04 16:27

    It depends on what you want the search to do:

    • if you want to find all matches, use the built-in grep:

      my @matches = grep { /pattern/ } @list_of_strings;
      
    • if you want to find the first match, use first in List::Util:

      use List::Util 'first';  
      my $match = first { /pattern/ } @list_of_strings;
      
    • if you want to find the count of all matches, use true in List::MoreUtils:

      use List::MoreUtils 'true';
      my $count = true { /pattern/ } @list_of_strings;
      
    • if you want to know the index of the first match, use first_index in List::MoreUtils:

      use List::MoreUtils 'first_index'; 
      my $index = first_index { /pattern/ } @list_of_strings;
      
    • if you want to simply know if there was a match, but you don't care which element it was or its value, use any in List::Util:

      use List::Util 1.33 'any';
      my $match_found = any { /pattern/ } @list_of_strings;
      

    All these examples do similar things at their core, but their implementations have been heavily optimized to be fast, and will be faster than any pure-perl implementation that you might write yourself with grep, map or a for loop.


    Note that the algorithm for doing the looping is a separate issue than performing the individual matches. To match a string case-insensitively, you can simply use the i flag in the pattern: /pattern/i. You should definitely read through perldoc perlre if you have not previously done so.

    0 讨论(0)
提交回复
热议问题