Occorrenze di sottostringhe in una stringa

Perché il seguente algoritmo non si ferma per me? (str è la stringa che sto cercando, findStr è la stringa che sto cercando di trovare)

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); 

L’ultima linea stava creando un problema. lastIndex non sarebbe mai a -1, quindi ci sarebbe un ciclo infinito. Questo può essere risolto spostando l’ultima riga di codice nel blocco 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); 

Che ne dici di usare StringUtils.countMatch da Apache Commons Lang?

 String str = "helloslkhellodjladfjhello"; String findStr = "hello"; System.out.println(StringUtils.countMatches(str, findStr)); 

Quel prodotto:

 3 

Your lastIndex += findStr.length(); è stato collocato al di fuori delle parentesi, causando un ciclo infinito (quando non è stata trovata alcuna occorrenza, lastIndex era sempre in findStr.length() ).

Ecco la versione fissa:

 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); 

Una versione più corta. 😉

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

Devi davvero gestire la corrispondenza da solo? Soprattutto se tutto ciò di cui hai bisogno è il numero di occorrenze, le espressioni regolari sono più ordinate:

 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); 
 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); 

alla fine del ciclo il conteggio è 3; spero che sia d’aiuto

Eccolo, racchiuso in un metodo piacevole e riutilizzabile:

 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; } 

Molte risposte date non riescono su uno o più di:

  • Modelli di lunghezza arbitraria
  • Corrispondenze sovrapposte (come il conteggio “232” in “23232” o “aa” in “aaa”)
  • Meta-caratteri dell’espressione regolare

Ecco cosa ho scritto:

 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; } 

Chiamata di esempio:

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

Se si desidera una ricerca con espressioni non regolari, è sufficiente compilare il modello in modo appropriato con il flag LITERAL :

 Pattern pattern = Pattern.compile("1+1", Pattern.LITERAL); int count = countMatches(pattern, "1+1+1"); // Returns 2 
 public int countOfOccurrences(String str, String subStr) { return (str.length() - str.replaceAll(Pattern.quote(subStr), "").length()) / subStr.length(); } 

Incrementa lastIndex ogni volta che cerchi la ricorrenza successiva.

Altrimenti trova sempre la prima sottostringa (nella posizione 0).

 public int indexOf(int ch, int fromIndex) 

Restituisce l’indice all’interno di questa stringa della prima occorrenza del carattere specificato, avviando la ricerca nell’indice specificato.

Quindi il tuo valore lastindex è sempre 0 e trova sempre ciao nella stringa.

Non posso credere che nessuno abbia menzionato questa fodera. È semplice, conciso ed è leggermente migliore di str.split(target, -1).length-1

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

È ansible numero di occorrenze utilizzando la funzione di libreria incorporata:

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

prova ad aggiungere lastIndex+=findStr.length() alla fine del tuo loop, altrimenti lastIndex+=findStr.length() in un ciclo infinito perché una volta trovata la sottostringa, stai provando a trovarla ancora e ancora dalla stessa ultima posizione.

Prova questo. Sostituisce tutte le partite con un - .

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

E se non vuoi distruggere il tuo str , puoi creare una nuova stringa con lo stesso contenuto:

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

Dopo aver eseguito questo blocco, questi saranno i tuoi valori:

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

La risposta data come corretta non è buona per contare cose come i ritorni a capo ed è troppo prolissa. Le risposte successive sono migliori ma tutte possono essere raggiunte semplicemente con

 str.split(findStr).length 

Non lascia cadere le partite finali usando l’esempio nella domanda.

Come suggerito da @Mr_and_Mrs_D:

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

In base alle risposte esistenti mi piacerebbe aggiungere una versione “più breve” senza il se:

 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 

Questo metodo sotto mostra quante volte la sottostringa viene ripetuta sull’intera stringa. Spero di usarti per intero: –

  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++; } } 

ecco l’altra soluzione senza usare regexp / patterns / matchers o anche senza usare StringUtils.

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

Se hai bisogno dell’indice di ciascuna sottostringa all’interno della stringa originale, puoi fare qualcosa con indexOf in questo modo:

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

Ecco la versione avanzata per contare quante volte il token si è verificato in una stringa immessa dall’utente:

 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); } } 
 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; 

}

Questa soluzione stampa il numero totale di occorrenza di una sottostringa data in tutta la stringa, inoltre include i casi in cui esistono corrispondenze sovrapposte.

 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 (mn) position while(index!=-1 && i<=(nm)){ 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); } 

}