J'ai quelques fonctions que je rencontre plus d'un million de fois sur divers textes, ce qui signifie que de petites améliorations dans ces fonctions se traduisent par de gros gains dans l'ensemble. Actuellement, j'ai remarqué que toutes mes fonctions qui impliquent des chiffres de mots prennent considérablement plus de temps que tout le reste, alors je pense que je veux essayer de faire du nombre de mots de manière différente.
Fondamentalement, quelle est ma fonction Saisissez un certain nombre d'objets qui ont un texte associé à eux, vérifiez que ce texte ne correspond pas à certains modèles, puis comptez le nombre de mots dans ce texte. Une version de base de la fonction est la suivante: p> Je fais beaucoup de comparaisons de texte similaires à ce que je fais ici ailleurs dans mon code, alors je suppose que mon Le problème doit être avec mon mot comptage. Y a-t-il un moyen plus rapide de le faire que de fractionnement sur \ s + code>? Si oui, qu'est-ce que c'est et pourquoi est-ce plus rapide (je peux donc comprendre ce que je fais mal et peut appliquer cette connaissance à des problèmes similaires plus tard). P> P>
5 Réponses :
Étant donné que vous n'avez besoin que du nombre de mots au lieu de la matrice de mots, il serait bon d'éviter d'utiliser Il remplace le travail de construction d'un tableau de mots avec le travail de substituer chaque mot avec lui-même. Vous auriez besoin de le repasser pour voir s'il est plus rapide. P> Edit: Cela peut être plus rapide: P> divisé code>. Quelque chose que cela pourrait fonctionner:
++$num_words while $text =~ /\S+/g;
Utiliser une boucle tandis que avec une regex est la manière la plus rapide que j'ai trouvée pour compter les mots: La boucle tandis que la boucle est plus rapide car la mémoire n'a pas besoin d'être allouée pour chacun des trouvé des mots. De plus, la regex est dans le contexte booléen, ce qui signifie qu'il n'a pas besoin d'extraire la correspondance réelle de la chaîne. P> p>
Agréable! Merci! C'est génial.
Formidable "pourquoi" aller avec le "quoi". Génial que vous avez souligné Benchmark Code> pour une utilisation dans d'autres expérimentations et optimisation.
Depuis que vous limitez le nombre de mots à 30, vous pouvez revenir de la fonction précédente: ou en utilisant divisé code>: p>
$num_words = () = split /\s+/, $text, 30;
Définitivement. J'ai intégré cela dans la réponse de @eric Strom.
Pour l'exactitude, de Réponse d'Aleroot , vous voulez probablement Pour la vitesse, car vous appuyez sur le nombre de mots à 30, vous souhaitez probablement utiliser la limite code> argument code> * : D'autre part, d'autres réponses vous détournent judicieusement de divisé" " code>, pas l'original
Split / \ s + / code> Pour éviter une erreur de clôture :
a "Split" sur "/ \ s + /" est comme une "Split (" ")" Sauf que toute personne de premier plan produit un premier champ nul. em> * Cette différence vous donnera un mot supplémentaire (le premier champ NULL, c'est-à-dire) par ligne. P>
divisé" ", $ str, 30 code>. p>.
Splitt code> complètement, car vous n'avez pas besoin de la liste des mots, juste leur compte. P>
Un mot supplémentaire par ligne avec des espaces de tête i>
Oui, bonne correction. Sur une ligne avec des espaces de premier plan, non sur aucune ligne du tout.
Si les mots ne sont séparés que par des espaces uniques, les espaces de comptage sont rapides. my $text = 'asdf asdf asdf asdf asdf';
sub count_array {
my @text_words = split(/\s+/, $text);
scalar(@text_words);
}
sub count_list {
my $x =()= $text =~ /\S+/g; #/
}
sub count_while {
my $num;
$num++ while $text =~ /\S+/g; #/
$num
}
sub count_tr {
1 + ($text =~ tr{ }{ });
}
say count_array; # 5
say count_list; # 5
say count_while; # 5
say count_tr; # 5
use Benchmark 'cmpthese';
cmpthese -2 => {
array => \&count_array,
list => \&count_list,
while => \&count_while,
tr => \&count_tr,
}
# Rate list while array tr
# list 220911/s -- -24% -44% -94%
# while 291225/s 32% -- -26% -92%
# array 391769/s 77% 35% -- -89%
# tr 3720197/s 1584% 1177% 850% --
Sauf si vous utilisez / D, la liste de remplacement des paramètres par défaut de la liste de saisie, donc tr / // code> est équivalent à
tr {} {} code>