6
votes

En utilisant une variable de caractère dans TR ///

J'essaie de compter les caractères d'une chaîne et j'ai trouvé une solution facile à compter un seul caractère à l'aide de l'opérateur tr code>. Maintenant, je veux faire cela avec chaque personnage d'A à Z. La solution suivante ne fonctionne pas car tr /// code> correspond à chaque caractère.

my @chars = ('a' .. 'z');
foreach my $c (@chars)
{
    $count{$c} = ($text =~ tr/$c//);
}


9 commentaires

Je ferais cela un peu différemment, vous pouvez remplacer n'importe quel caractère qui n'est pas quelque chose de [A-Z] avec rien et comptez les restes.


Je veux savoir combien il y a de chaque personnage, pas de la classe de caractère entière.


Maintenant, vous avez 2 problèmes? Y a-t-il une raison pour laquelle vous ne voulez pas simplement itérer via $ texte et incrémenter la comptoir de chaque lettre comme vous le voyez?


À mon avis, le commentaire de WOOBLE est un moyen plus efficace de le faire que n'importe laquelle des réponses ci-dessous (alors j'ai donné un up :))


J'ai lu que tr est beaucoup plus rapide que itérant sur le texte.


Merci pour toutes vos réponses rapides. J'ai voté pour Eugènes parce que c'est le plus simple et le plus proche de ce que je voulais.


@ André: tr est sans aucun doute plus rapide que itérant lorsque vous remplacez un ensemble de caractères avec un autre. Faire 26 tr S, d'autre part, presque certainement ne sera certainement pas (bien que je n'ai pas été comparé).


D'accord avec @wooble. L'utilisation de cette approche est de loin une manière inefficace de le faire. De plus, vous manquez des caractères majuscules ici.


OK bon à savoir. Majuscule n'est pas un problème parce que j'ai fait un LC () avant. Ne l'a pas posté parce que c'est sans importance ;-)


6 Réponses :


7
votes

tr /// ne fonctionne pas avec des variables sauf si vous l'enveloppez dans un eval

mais il y a un moyen plus agréable de le faire: xxx

pour Timtowtdi: xxx


4 commentaires

C'est une belle solution pour mon problème, mais cela ne répond pas à ma question comment utiliser la regex avec la variable. J'ai donc dû accepter les Eugènes. Pardon!


@ André: tr /// est pas une opération de regex, bien que la construction puisse sembler similaire


Notez que si l'un des caractères que vous recherchez est des métacaracters regex (comme . , ? , * ) au lieu de seulement az, vous besoin de leur échapper dans la première solution. Vous pouvez le faire en ajoutant \ q à la regex: $ comptez {$ _} = () = ~ / \ q $ _ / g pour '. ',' * ';


Ces deux méthodes ne sont pas tout à fait les mêmes. La première méthode (recherche de $ _ ) produira un hachage avec 26 touches --- une pour chaque lettre de l'alphabet --- Peu importe si ces lettres apparaissent dans $ texte . Le hachage produit par la deuxième méthode (en utilisant grep ) n'aura que des paires de clés pour les touches qui apparaissent dans $ texte .



1
votes

du Documentation Perlop :

foreach my $c (@chars) {
   $count{$c} += ($text =~ s/$c//g);
}


0 commentaires

3
votes

Si vous regardez le perdoc pour tr / Gestion de la recherche / remplacement / CDSR , puis vous verrez, juste au bas de la section, les suivantes:

Parce que la table de translittération est construite au moment de la compilation, ni la commande de la recherche ni la liste de remplacement ne sont soumises à une double interpolation de citation. Cela signifie que si vous souhaitez utiliser des variables, vous devez utiliser un eval (): xxx

Ainsi, vous auriez donc besoin d'un eval pour générer une nouvelle déchets de recherche.

Ceci va être très inefficace ... Le code pourrait être soigné , mais vous traitez la chaîne complète 26 fois. Vous ne comptez pas non plus de caractères majuscules.

Vous seriez mieux à travers la chaîne une fois et incrémenter simplement des compteurs pour chaque personnage trouvé.


0 commentaires

6
votes

TR ne pas Soutenez l'interpolation variable (ni dans la liste de recherche ni dans la liste de remplacement). Si vous souhaitez utiliser des variables, vous devez utiliser eval () : xxx

qui dit, une approche plus efficace (et sécurisée) serait de simplement itérer sur la Personnages dans la chaîne et les compteurs d'incrément pour chaque caractère, par exemple: xxx


2 commentaires

Cela fonctionne bien. Pourriez-vous expliquer pourquoi il y a une barre oblique contraire avant $ texte ? Je suis nouveau à Perl :-)


André: Il empêche l'interpolation de la variable texte dans la chaîne, c'est-à-dire eval voit la chaîne comme '$ text = ~ tr / a / a /' / code>



1
votes

Ma solution avec une modification basée sur http://www.perlmonks.org/?node_id=446003 xxx


0 commentaires

1
votes

Vous pouvez utiliser s à la place. La substitution est beaucoup plus puissante que tr

ma solution: xxx

g à la fin signifie "l'utiliser globalement ".

voir:


0 commentaires