Méthode simple pour compter les occurrences de caractères dans une chaîne

Existe-t-il un moyen simple (au lieu de parcourir manuellement toute la chaîne ou boucle pour indexOf) afin de trouver combien de fois un caractère apparaît dans une chaîne?

Disons que nous avons “abdsd3 $ asda $ asasdd $ sadas” et nous voulons que $ apparaisse 3 fois.

Ssortingng s = "..."; int counter = 0; for( int i=0; i 

C'est certainement le moyen le plus rapide. Les expressions rationnelles sont beaucoup plus lentes ici et plus difficiles à comprendre.

Style fonctionnel (Java 8, juste pour le plaisir):

 str.chars().filter(num -> num == '$').count() 

Moyen non optimal, mais simple de compter les occurrences:

 Ssortingng s = "..."; int counter = s.split("\\$", -1).length - 1; 

Remarque:

  • Le signe dollar est un symbole spécial d’expression régulière, il doit donc être échappé avec une barre oblique inverse.
  • Une barre oblique inverse est un symbole spécial pour les caractères d’échappement tels que les nouvelles lignes. Il doit donc être précédé d’une barre oblique inverse.
  • Le second argument de split empêche la suppression des chaînes de suivi vides.

Vous pouvez utiliser Apache Commons ‘ SsortingngUtils.countMatches(Ssortingng ssortingng, Ssortingng subSsortingngToCount) .

Comme vous parsingz la chaîne entière de toute façon, vous pouvez créer un nombre de caractères complet et effectuer un nombre quelconque de recherches, le tout pour le même coût (n):

 public static Map getCharFreq(Ssortingng s) { Map charFreq = new HashMap(); if (s != null) { for (Character c : s.toCharArray()) { Integer count = charFreq.get(c); int newCount = (count==null ? 1 : count+1); charFreq.put(c, newCount); } } return charFreq; } // ... Ssortingng s = "abdsd3$asda$asasdd$sadas"; Map counts = getCharFreq(s); counts.get('$'); // => 3 counts.get('a'); // => 7 counts.get('s'); // => 6 

Un comptage de fréquence de caractères est une tâche courante pour certaines applications (telles que la formation), mais pas suffisamment générale pour justifier son intégration aux principales API Java. En tant que tel, vous devrez probablement écrire votre propre fonction.

vous pouvez également utiliser un pour chaque boucle. Je pense que c’est plus simple à lire.

 int occurrences = 0; for(char c : yourSsortingng.toCharArray()){ if(c == '$'){ occurrences++; } } 

Traverser la chaîne est probablement la plus efficace, bien que l’utilisation de Regex pour cela puisse produire un code plus propre (bien que vous puissiez toujours cacher votre code de cheminement dans une fonction).

Eh bien, il y a un tas d’utilitaires différents pour cela, par exemple Apache Commons Lang Ssortingng Utils

mais à la fin, il doit parcourir la chaîne pour compter les occurrences d’une manière ou d’une autre.

Notez également que la méthode countMatches ci-dessus possède la signature suivante et fonctionnera donc également pour les sous-chaînes.

public static int countMatches(Ssortingng str, Ssortingng sub)

La source de ceci est (d’ ici ):

 public static int countMatches(Ssortingng str, Ssortingng sub) { if (isEmpty(str) || isEmpty(sub)) { return 0; } int count = 0; int idx = 0; while ((idx = str.indexOf(sub, idx)) != -1) { count++; idx += sub.length(); } return count; } 

J’étais curieux de savoir s’ils parcouraient la chaîne ou utilisaient Regex.

Je crois que le “one liner” que vous vous attendiez à obtenir est le suivant:

 "abdsd3$asda$asasdd$sadas".replaceAll( "[^$]*($)?", "$1" ).length(); 

Rappelez-vous que les exigences sont les suivantes:

( au lieu de parcourir manuellement toute la chaîne ou boucle pour indexOf )

Et permettez-moi d’append: au cœur de cette question, on dirait que “n’importe quelle boucle” n’est pas souhaitée et qu’il n’y a aucune exigence de vitesse. Je crois que le sous-texte de cette question est le facteur de fraîcheur .

Quelque chose de plus fonctionnel, sans Regex:

 public static int count(Ssortingng s, char c) { return s.length()==0 ? 0 : (s.charAt(0)==c ? 1 : 0) + count(s.subssortingng(1),c); } 

Il n’y a pas de queue récursive, par souci de clarté.

Vous pouvez envisager de sortinger la chaîne – traitez-la comme un tableau de caractères – puis effectuez une recherche binary modifiée qui compte les occurrences? Mais je suis d’accord avec @tofutim que la traverser est la plus efficace – O (N) contre O (N * logN) + O (logN)

C’est un code simple, mais un peu moins rapide.

 Ssortingng s = ...; int countDollar = s.length()-s.replaceAll("\\$","").length(); int counta = s.length()-s.replaceAll("a","").length(); 

Une réponse encore meilleure est ici en double

Il existe un autre moyen de compter le nombre de caractères dans chaque chaîne. En supposant que nous avons une chaîne de caractères comme Ssortingng str = "abfdvdvdfv"

Nous pouvons alors compter le nombre de fois que chaque caractère apparaît en traversant une seule fois

 for (int i = 0; i < str.length(); i++) { if(null==map.get(str.charAt(i)+"")) { map.put(str.charAt(i)+"", new Integer(1)); } else { Integer count = map.get(str.charAt(i)+""); map.put(str.charAt(i)+"", count+1); } } 

Nous pouvons alors vérifier la sortie en parcourant la carte comme

 for (Map.Entry entry:map.entrySet()) { System.out.println(entry.getKey()+" count is : "+entry.getValue()) } 
  public static int countChars(Ssortingng input,char find){ if(input.indexOf(find) != -1){ return countChars(input.subssortingng(0, input.indexOf(find)), find)+ countChars(input.subssortingng(input.indexOf(find)+1),find) + 1; } else { return 0; } }