web-dev-qa-db-fra.com

Compter le nombre d'occurrences d'une chaîne dans une autre (Perl)

Quel est le moyen le plus rapide de compter le nombre de fois qu'une certaine chaîne apparaît dans une plus grande? Ma meilleure supposition serait de remplacer toutes les instances de cette chaîne par rien, de calculer la différence de longueurs et de diviser par la longueur de la sous-chaîne, mais cela semble plutôt lent, et j'ai besoin d'analyser de grandes quantités de données.

34
ronash

Vous pouvez capturer les chaînes, puis les compter. Cela peut être fait en appliquant un contexte de liste à la capture avec ():

my $x = "foo";
my $y = "foo foo foo bar";
my $c = () = $y =~ /$x/g;  # $c is now 3

Vous pouvez également capturer dans un tableau et compter le tableau. Même principe, technique différente:

my @c = $y =~ /$x/g;
my $count = @c;
63
TLP
my $string = "aaaabbabbba";
my @count = ($string =~ /a/g);
print @count . "\n";

ou

my $count = ($string =~ s/a/a/g);
15
Brian Roach

Vous pouvez utiliser une expression régulière globale. Quelque chose comme:

my @matches = $bigstring =~ /($littlestring)/g;
my $count = @matches;
9
MattLBeck

Juste pour être complet, vous pouvez appeler à plusieurs reprises la fonction d'index dans une boucle et compter toutes les fois où elle a renvoyé l'index de la sous-chaîne dans la chaîne et modifier la position de départ. Cela éviterait d'utiliser des expressions régulières, et dans mes tests, c'est un peu plus rapide que les solutions d'expressions régulières.

J'ai adapté un sous-marin pour le faire à partir d'ici: http://www.misc-Perl-info.com/Perl-index.html

sub occurrences {

    my( $x, $y ) = @_;

    my $pos = 0;
    my $matches = 0;

    while (1) {
        $pos = index($y, $x, $pos);
        last if($pos < 0);
        $matches++;
        $pos++;
    }   

    return $matches;
}
5
Matthew Lock