it-swarm.com.de

Wie suche ich in einem Perl-Array nach einer passenden Zeichenfolge?

Was ist die intelligenteste Methode zum Durchsuchen eines Arrays von Zeichenfolgen nach einer übereinstimmenden Zeichenfolge in Perl?

Ich möchte, dass bei der Suche die Groß- und Kleinschreibung nicht beachtet wird

so "aAa" wäre in ("aaa","bbb")

36
Mike

Ich vermute

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

würde den Trick machen.

29
Peter Tillemans

Es kommt darauf an, was die Suche bewirken soll:

  • wenn Sie alle Übereinstimmungen finden möchten , verwenden Sie das eingebaute grep :

    my @matches = grep { /pattern/ } @list_of_strings;
    
  • wenn Sie die erste Übereinstimmung finden möchten , verwenden Sie first in List :: Util :

    use List::Util 'first';  
    my $match = first { /pattern/ } @list_of_strings;
    
  • wenn Sie die Anzahl aller Übereinstimmungen ermitteln möchten, verwenden Sie true in List :: MoreUtils :

    use List::MoreUtils 'true';
    my $count = true { /pattern/ } @list_of_strings;
    
  • wenn Sie den Index der ersten Übereinstimmung kennen möchten, verwenden Sie first_index in List :: MoreUtils :

    use List::MoreUtils 'first_index'; 
    my $index = first_index { /pattern/ } @list_of_strings;
    
  • wenn Sie einfach wissen möchten , ob es eine Übereinstimmung gab , aber es Ihnen egal ist, welches Element es war oder welchen Wert es hat, verwenden Sie any in List :: Util :

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

Alle diese Beispiele haben im Kern ähnliche Funktionen, aber ihre Implementierungen wurden stark optimiert, um schnell zu sein. Sie sind schneller als jede reine Perl-Implementierung, mit der Sie möglicherweise selbst geschrieben haben grep , map oder ein for loop .


Beachten Sie, dass der Algorithmus zum Durchführen der Schleife ein anderes Problem darstellt als das Durchführen der einzelnen Übereinstimmungen. Um eine Zeichenfolge unabhängig von Groß- und Kleinschreibung zu finden, können Sie einfach das Flag i im Muster verwenden: /pattern/i. Sie sollten unbedingt perldoc perlre durchlesen, falls Sie dies noch nicht getan haben.

143
Ether

Perl 5.10+ enthält den 'Smart-Match'-Operator ~~, der true zurückgibt, wenn ein bestimmtes Element in einem Array oder Hash enthalten ist, und false, wenn dies nicht der Fall ist (siehe perlfaq4 ):

Das Schöne daran ist, dass es auch reguläre Ausdrücke unterstützt, was bedeutet, dass Ihre Anforderung, bei der die Groß- und Kleinschreibung nicht berücksichtigt wird, problemlos erfüllt werden kann:

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!"
29
Zaid

Wenn Sie viele Suchen des Arrays durchführen, ist UND immer passend definiert als Zeichenkettenäquivalenz, dann können Sie Ihre Daten normalisieren und einen Hash verwenden.

my @strings = qw( aAa Bbb cCC DDD eee );

my %string_lut;

# Init via slice:
@string_lut{ map uc, @strings } = ();

# or use a for loop:
#    for my $string ( @strings ) {
#        $string_lut{ uc($string) } = undef;
#    }


#Look for a string:

my $search = 'AAa';

print "'$string' ", 
    ( exists $string_lut{ uc $string ? "IS" : "is NOT" ),
    " in the array\n";

Lassen Sie mich betonen, dass ein Hash-Lookup gut ist, wenn Sie vorhaben, viele Lookups auf dem Array durchzuführen. Es wird auch nur funktionieren, wenn Matching bedeutet, dass $foo eq $bar oder andere Anforderungen, die durch Normalisierung erfüllt werden können (z. B. Groß-/Kleinschreibung).

6
daotoad
#!/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;
5
Alex Reynolds

Perl-String-Übereinstimmung kann auch für ein einfaches Ja/Nein verwendet werden.

my @foo=("hello", "world", "foo", "bar");

if ("@foo" =~ /\bhello\b/){
    print "found";
}
else{
    print "not found";
}
2
Coke Fiend

Für nur ein boolesches Übereinstimmungsergebnis oder für eine Anzahl von Vorkommen können Sie Folgendes verwenden:

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"
    };
}

Ausgabe:

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'

Muss nicht verwenden ein Modul.
Natürlich ist es weniger "erweiterbar" und vielseitig wie irgendein Code oben.
Ich verwende dies für interaktive Benutzerantworten, um sie mit einem vordefinierten Satz von Antworten zu vergleichen, bei denen die Groß- und Kleinschreibung nicht berücksichtigt wird.

1