622 votes

Comment compter le nombre d'occurrences d'un caractère dans une chaîne ?

J'ai la chaîne

a.b.c.d

Je veux compter les occurrences de "." d'une manière idiomatique, de préférence en une seule phrase.

(Auparavant, j'avais exprimé cette contrainte par "sans boucle", au cas où vous vous demanderiez pourquoi tout le monde essaie de répondre sans utiliser de boucle).

1 votes

Des devoirs ? Parce que sinon je ne vois pas l'obligation d'éviter la boucle.

26 votes

Je ne suis pas contre une boucle, je cherche plutôt une phrase idiomatique.

2 votes

Les boucles ont été faites pour un problème comme celui-ci, écrivez la boucle dans une classe d'utilité commune puis appelez votre one liner tout frais.

1124voto

Andreas Wederbrand Points 10606

Que dites-vous de ça ? Elle n'utilise pas de regexp en dessous et devrait donc être plus rapide que certaines des autres solutions et n'utilise pas de boucle.

int count = line.length() - line.replace(".", "").length();

130 votes

Le moyen le plus simple. La plus intelligente. Et elle fonctionne sur Android, où il n'y a pas de classe StringUtils.

47 votes

C'est la meilleure réponse. La raison pour laquelle c'est la meilleure est que vous n'avez pas besoin d'importer une autre bibliothèque.

5 votes

Elle n'est pas nécessairement plus rapide que d'autres solutions comme StringUtils.countMatches car il doit allouer de la mémoire pour la chaîne retournée. Cela reste une bonne solution lorsque les performances ne sont pas critiques.

784voto

Cowan Points 17235

Ma "phrase idiomatique" à ce sujet est la suivante :

int count = StringUtils.countMatches("a.b.c.d", ".");

Pourquoi l'écrire vous-même alors qu'il est déjà dans le livre de bord ? langue commune ?

L'oneliner de Spring Framework pour cela est :

int occurance = StringUtils.countOccurrencesOf("a.b.c.d", ".");

44 votes

Goyave équivalent : int count = CharMatcher.is('.').countIn("a.b.c.d"); ...Comme réponse de dogbane dans une question dupliquée.

29 votes

Même si je ne vais pas le décréter, (a) il nécessite des librairies tierces et (b) il est coûteux.

0 votes

Cela ne fonctionne qu'avec les cadres à ressort à importer.

184voto

Jon Skeet Points 692016

Tôt ou tard, quelque chose doit tourner en boucle. Il est beaucoup plus simple pour vous d'écrire la boucle (très simple) que d'utiliser quelque chose comme split ce qui est beaucoup plus puissant que ce dont vous avez besoin.

Par tous les moyens, encapsulez la boucle dans une méthode distincte, par ex.

public static int countOccurrences(String haystack, char needle)
{
    int count = 0;
    for (int i=0; i < haystack.length(); i++)
    {
        if (haystack.charAt(i) == needle)
        {
             count++;
        }
    }
    return count;
}

Vous n'avez donc pas besoin d'avoir la boucle dans votre code principal - mais la boucle doit être présente quelque part.

6 votes

For (int i=0,l=haystack.length() ; i < l ; i++) soyez gentil avec votre pile

12 votes

(Je ne suis même pas sûr de savoir d'où vient la partie "pile" du commentaire. Ce n'est pas comme este La réponse est ma réponse récursive, qui est en effet méchante pour la pile).

3 votes

Non seulement ça mais c'est peut-être une anti-optimisation sans regarder ce que fait le jit. Si vous faites ce qui précède sur un tableau pour une boucle par exemple, vous pourriez empirer les choses.

62voto

PhiLho Points 23458

J'ai eu une idée similaire à celle de Mladen, mais à l'opposé...

String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);

0 votes

Correct. ReplaceAll(".") remplacerait n'importe quel caractère, pas seulement le point. ReplaceAll(". \\. ") aurait fonction pour fonctionner. Votre solution est plus simple.

0 votes

Jjnguy avait en fait suggéré un replaceAll("[^.]") en premier, en voyant mon "a.b.c.d".split(" \\. ").length-1 solution. Mais après avoir été frappé 5 fois, j'ai supprimé ma réponse (et son commentaire).

0 votes

"...maintenant vous avez deux problèmes" (oblig.) De toute façon, je parierais qu'il y a des dizaines de boucles qui s'exécutent en replaceAll() y length() . Eh bien, si elle n'est pas visible, elle n'existe pas ;o)

39voto

Mladen Prajdic Points 10337
String s = "a.b.c.d";
int charCount = s.length() - s.replaceAll("\\.", "").length();

ReplaceAll(".") remplacerait tous les caractères.

La solution de PhiLho utilise ReplaceAll("[^.]",""), qui n'a pas besoin d'être échappé, puisque [.] représente le caractère "point", et non "tout caractère".

0 votes

J'aime bien celui-là. Il y a toujours une boucle, bien sûr, comme il se doit.

0 votes

Notez que vous devrez diviser ce nombre si vous souhaitez rechercher des sous-chaînes de longueur > 1.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X