web-dev-qa-db-fra.com

Occurrences de sous-chaîne dans une chaîne

Pourquoi l’algorithme suivant ne s’arrête-t-il pas pour moi? (Str est la chaîne dans laquelle je cherche, findStr est la chaîne que je cherche)

String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;

while (lastIndex != -1) {
    lastIndex = str.indexOf(findStr,lastIndex);

    if( lastIndex != -1)
        count++;

    lastIndex += findStr.length();
}

System.out.println(count);
106
bobcom

La dernière ligne créait un problème. lastIndex ne serait jamais à -1, donc il y aurait une boucle infinie. Cela peut être corrigé en déplaçant la dernière ligne de code dans le bloc if.

String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;

while(lastIndex != -1){

    lastIndex = str.indexOf(findStr,lastIndex);

    if(lastIndex != -1){
        count ++;
        lastIndex += findStr.length();
    }
}
System.out.println(count);
80
codebreach

Que diriez-vous d'utiliser StringUtils.countMatches d'Apache Commons Lang?

String str = "helloslkhellodjladfjhello";
String findStr = "hello";

System.out.println(StringUtils.countMatches(str, findStr));

Cela génère:

3
173
A_M

Votre lastIndex += findStr.length(); a été placé en dehors des crochets, provoquant une boucle infinie (quand aucune occurrence n'a été trouvée, lastIndex était toujours à findStr.length()). 

Voici la version corrigée:

String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;

while (lastIndex != -1) {

    lastIndex = str.indexOf(findStr, lastIndex);

    if (lastIndex != -1) {
        count++;
        lastIndex += findStr.length();
    }
}
System.out.println(count);
105
Olivier

Une version plus courte. ;)

String str = "helloslkhellodjladfjhello";
String findStr = "hello";
System.out.println(str.split(findStr, -1).length-1);
81
Peter Lawrey

Devez-vous vraiment faire la correspondance vous-même? Surtout si vous n'avez besoin que du nombre d'occurrences, les expressions régulières sont plus ordonnées:

String str = "helloslkhellodjladfjhello";
Pattern p = Pattern.compile("hello");
Matcher m = p.matcher(str);
int count = 0;
while (m.find()){
    count +=1;
}
System.out.println(count);     
78
Jean

Le voici, emballé dans une méthode agréable et réutilisable:

public static int count(String text, String find) {
        int index = 0, count = 0, length = find.length();
        while( (index = text.indexOf(find, index)) != -1 ) {                
                index += length; count++;
        }
        return count;
}
9
momomo
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int lastIndex = 0;
int count = 0;

while((lastIndex = str.indexOf(findStr, lastIndex)) != -1) {
     count++;
     lastIndex += findStr.length() - 1;
}
System.out.println(count);

à la fin de la boucle, le nombre est 3; J'espère que ça aide

8
dfa
public int countOfOccurrences(String str, String subStr) {
  return (str.length() - str.replaceAll(Pattern.quote(subStr), "").length()) / subStr.length();
}
6
Maksym Ovsianikov

Un grand nombre des réponses données échouent sur un ou plusieurs des problèmes suivants:

  • Patrons de longueur arbitraire
  • Chevauchement des correspondances (par exemple, en comptant "232" dans "23232" ou "aa" dans "aaa")
  • Méta-caractères d'expression régulière

Voici ce que j'ai écrit:

static int countMatches(Pattern pattern, String string)
{
    Matcher matcher = pattern.matcher(string);

    int count = 0;
    int pos = 0;
    while (matcher.find(pos))
    {
        count++;
        pos = matcher.start() + 1;
    }

    return count;
}

Exemple d'appel:

Pattern pattern = Pattern.compile("232");
int count = countMatches(pattern, "23232"); // Returns 2

Si vous souhaitez une recherche avec une expression non régulière, il vous suffit de compiler votre modèle de manière appropriée avec l'indicateur LITERAL:

Pattern pattern = Pattern.compile("1+1", Pattern.LITERAL);
int count = countMatches(pattern, "1+1+1"); // Returns 2
5
benkc

Je suis très surpris que personne n'ait mentionné cette doublure. C'est simple, concis et fonctionne légèrement mieux que str.split(target, -1).length-1

public static int count(String str, String target) {
    return (str.length() - str.replace(target, "").length()) / target.length();
}
4
kmecpp

Incrémentez lastIndex chaque fois que vous recherchez l'occurrence suivante. 

Sinon, on trouve toujours la première sous-chaîne (en position 0).

3
Stanislav Kniazev
public int indexOf(int ch,
                   int fromIndex)

Retourne l'index dans cette chaîne de la première occurrence du caractère spécifié, démarrant la recherche à l'index spécifié.

Donc, votre valeur lastindex est toujours 0 et il trouve toujours hello dans la chaîne.

3
Bhushan Bhangale

Vous pouvez nombre d'occurrences en utilisant la fonction de bibliothèque intégrée:

import org.springframework.util.StringUtils;
StringUtils.countOccurrencesOf(result, "R-")
2
Victor

essayez d’ajouter lastIndex+=findStr.length() à la fin de votre boucle, sinon vous vous retrouverez dans une boucle sans fin car une fois que vous avez trouvé la sous-chaîne, vous essayez de la retrouver encore et encore à partir de la même position.

1

Essaye celui-là. Il remplace toutes les correspondances avec un -.

String str = "helloslkhellodjladfjhello";
String findStr = "hello";
int numberOfMatches = 0;
while (str.contains(findStr)){
    str = str.replaceFirst(findStr, "-");
    numberOfMatches++;
}

Et si vous ne voulez pas détruire votre str, vous pouvez créer une nouvelle chaîne avec le même contenu:

String str = "helloslkhellodjladfjhello";
String strDestroy = str;
String findStr = "hello";
int numberOfMatches = 0;
while (strDestroy.contains(findStr)){
    strDestroy = strDestroy.replaceFirst(findStr, "-");
    numberOfMatches++;
}

Après avoir exécuté ce bloc, ce seront vos valeurs:

str = "helloslkhellodjladfjhello"
strDestroy = "-slk-djladfj-"
findStr = "hello"
numberOfMatches = 3
1
Xander

La réponse correcte n'est pas bonne pour compter des choses telles que les retours à la ligne et est beaucoup trop verbeuse. Les réponses ultérieures sont meilleures, mais tout peut être obtenu simplement avec

str.split(findStr).length

Il ne supprime pas les correspondances suivantes à l'aide de l'exemple de la question.

1
Mark

Comme @Mr_and_Mrs_D l'a suggéré:

String haystack = "hellolovelyworld";
String needle = "lo";
return haystack.split(Pattern.quote(needle), -1).length - 1;
1
Ron Tesler

Sur la base des réponses existantes, j'aimerais ajouter une version "plus courte" sans le if:

String str = "helloslkhellodjladfjhello";
String findStr = "hello";

int count = 0, lastIndex = 0;
while((lastIndex = str.indexOf(findStr, lastIndex)) != -1) {
    lastIndex += findStr.length() - 1;
    count++;
}

System.out.println(count); // output: 3
1
sjkm

voici l’autre solution sans utiliser regexp/patterns/matchers ni même avec StringUtils.

String str = "helloslkhellodjladfjhelloarunkumarhelloasdhelloaruhelloasrhello";
        String findStr = "hello";
        int count =0;
        int findStrLength = findStr.length();
        for(int i=0;i<str.length();i++){
            if(findStr.startsWith(Character.toString(str.charAt(i)))){
                if(str.substring(i).length() >= findStrLength){
                    if(str.substring(i, i+findStrLength).equals(findStr)){
                        count++;
                    }
                }
            }
        }
        System.out.println(count);
0

Cette solution imprime le nombre total d'occurrences d'une sous-chaîne donnée tout au long de la chaîne, ainsi que les cas où des correspondances se chevauchent.

class SubstringMatch{
 public static void main(String []args){
    //String str = "aaaaabaabdcaa";
    //String sub = "aa";
    //String str = "caaab";
    //String sub = "aa";
    String str="abababababaabb";
    String sub = "bab";

    int n = str.length();
    int m = sub.length();

    // index=-1 in case of no match, otherwise >=0(first match position)
    int index=str.indexOf(sub), i=index+1, count=(index>=0)?1:0;
    System.out.println(i+" "+index+" "+count);

    // i will traverse up to only (m-n) position
    while(index!=-1 && i<=(n-m)){   
        index=str.substring(i, n).indexOf(sub);
        count=(index>=0)?count+1:count;
        i=i+index+1;  
        System.out.println(i+" "+index);
    }
    System.out.println("count: "+count);
 }

}

0
Anubhav Singh

La méthode ci-dessous montre combien de fois la sous-chaîne de temps est répétée sur toute la chaîne. J'espère utiliser plein pour vous: -

    String search_pattern="aaa";
    String whole_pattern=""aaaaaababaaaaaa;
    int j = search_pattern.length();
    for (int i = 0; i < whole_pattern.length() - j + 1; i++) {

        String str1 = whole_pattern.substring(i, j + i);

        System.out.println("sub string loop " + i + " => " + str1);

        if (str1.equals(search_pattern)) {
            Constants.k++;
        }

    }
0
duggu

Si vous avez besoin de l'index de chaque sous-chaîne dans la chaîne d'origine, vous pouvez faire quelque chose avec indexOf comme ceci:

 private static List<Integer> getAllIndexesOfSubstringInString(String fullString, String substring) {
    int pointIndex = 0;
    List<Integer> allOccurences = new ArrayList<Integer>();
    while(fullPdfText.indexOf(substring,pointIndex) >= 0){
       allOccurences.add(fullPdfText.indexOf(substring, pointIndex));
       pointIndex = fullPdfText.indexOf(substring, pointIndex) + substring.length();
    }
    return allOccurences;
}
0
Rhino

Voici la version avancée pour compter combien de fois le jeton s'est produit dans une chaîne entrée par l'utilisateur:

public class StringIndexOf {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        System.out.println("Enter a sentence please: \n");
        String string = scanner.nextLine();

        int atIndex = 0;
        int count = 0;

        while (atIndex != -1)
        {
            atIndex = string.indexOf("hello", atIndex);

            if(atIndex != -1)
            {
                count++;
                atIndex += 5;
            }
        }

        System.out.println(count);
    }

}
0
Venzentx
public static int getCountSubString(String str , String sub){
int n = 0, m = 0, counter = 0, counterSub = 0;
while(n < str.length()){
  counter = 0;
  m = 0;
  while(m < sub.length() && str.charAt(n) == sub.charAt(m)){
    counter++;
    m++; n++;
  }
  if (counter == sub.length()){
    counterSub++;
    continue;
  }
  else if(counter > 0){
    continue;
  }
  n++;
}

return  counterSub;

}

0
Nikolai Nechai