Wie zähle ich die Anzahl der Vorkommen eines Zeichens in einem String?

547

Ich habe die Schnur

a.b.c.d

Ich möchte die Vorkommen von '.' auf eine idiomatische Weise, vorzugsweise ein Einzeiler.

(Zuvor hatte ich diese Einschränkung als "ohne Schleife" ausgedrückt, falls Sie sich fragen, warum alle versuchen, ohne Schleife zu antworten.)

Bart
quelle
1
Hausaufgaben? Denn sonst sehe ich nicht die Notwendigkeit, die Schleife zu vermeiden.
PhiLho
22
Nicht abgeneigt von einer Schleife, sondern auf der Suche nach einem idiomatischen Einzeiler.
Bart
2
Für ein Problem wie dieses wurden Schleifen erstellt. Schreiben Sie die Schleife in eine allgemeine Utility-Klasse und rufen Sie dann Ihren frisch geprägten Einzeiler auf.
Che Javara
Ähnliche Frage für Zeichenfolgen: stackoverflow.com/questions/767759/…
koppor
Nur um darauf hinzuweisen - ich schätze es, die Einzeiler zu finden, es macht Spaß und ist (als echter Vorteil) oft leicht zu merken, aber ich möchte darauf hinweisen, dass eine separate Methode und eine Schleife in nahezu jeder Hinsicht besser sind - Lesbarkeit und gleichmäßige Leistung. Die meisten der unten aufgeführten "eleganten" Lösungen werden nicht sehr gut funktionieren, da sie das Reformieren von Zeichenfolgen / das Kopieren des Speichers umfassen, während eine Schleife, die nur die Zeichenfolge scannt und Vorkommen zählt, schnell und einfach wäre. Nicht, dass die Leistung im Allgemeinen ein Faktor sein sollte, aber schauen Sie nicht auf die einzeilige Schleife und gehen Sie davon aus, dass sie eine bessere Leistung erbringt.
Bill K

Antworten:

722

Mein 'idiomatischer Einzeiler' dafür ist:

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

Warum selbst schreiben, wenn es bereits in Commons Lang ist ?

Der Oneliner von Spring Framework hierfür ist:

int occurance = StringUtils.countOccurrencesOf("a.b.c.d", ".");
Cowan
quelle
44
Guava - Äquivalent: int count = CharMatcher.is('.').countIn("a.b.c.d");... Wie beantwortet dogbane in einer doppelten Frage.
Jonik
25
Obwohl ich dies nicht ablehnen werde, ist es (a) für Bibliotheken von Drittanbietern erforderlich und (b) teuer.
Javadba
Dies funktioniert nur mit Federrahmen, die importiert werden müssen.
Isuru Madusanka
19
Was in jedem Unternehmen, in dem ich gearbeitet habe, teuer war, sind viele schlecht geschriebene und schlecht gepflegte "* Utils" -Klassen. Teil Ihrer Arbeit ist es, zu wissen, was in Apache Commons verfügbar ist.
AbuNassar
1016

Wie wäre es damit. Es verwendet keinen regulären Ausdruck darunter, sollte also schneller sein als einige der anderen Lösungen und keine Schleife verwenden.

int count = line.length() - line.replace(".", "").length();
Andreas Wederbrand
quelle
122
Einfachster Weg. Clever. Und es funktioniert auf Android, wo es keine StringUtils-Klasse gibt
Jose_GD
43
Dies ist die beste Antwort. Der Grund dafür ist, dass Sie keine weitere Bibliothek importieren müssen.
Alex Spencer
27
Sehr praktisch, aber höllisch hässlich. Ich empfehle es nicht, da es zu verwirrendem Code führt.
Daniel San
32
Hässlicher Code kann minimiert werden, indem er zu einer Methode in Ihrer eigenen "StringUtils" -Klasse gemacht wird. Dann befindet sich der hässliche Code genau an einer Stelle und ist überall gut lesbar.
RonR
30
Die Schleifenmethode ist viel schneller. Insbesondere, wenn Sie ein Zeichen anstelle eines Strings zählen möchten (da es keine String.replace-Methode (char, char) gibt). Bei einer Zeichenfolge mit 15 Zeichen erhalte ich eine Differenz von 6049 ns gegenüber 26.739 ns (gemittelt über 100 Runs). Rohe Zahlen sind ein großer Unterschied, aber percetage weise ... es summiert sich. Vermeiden Sie die Speicherzuordnungen - verwenden Sie eine Schleife!
Ben
282

Fassen Sie andere Antworten zusammen und wissen Sie, wie ich dies mit einem Einzeiler tun kann:

   String testString = "a.b.c.d";

1) Verwenden von Apache Commons

int apache = StringUtils.countMatches(testString, ".");
System.out.println("apache = " + apache);

2) Verwenden von Spring Frameworks

int spring = org.springframework.util.StringUtils.countOccurrencesOf(testString, ".");
System.out.println("spring = " + spring);

3) Mit ersetzen

int replace = testString.length() - testString.replace(".", "").length();
System.out.println("replace = " + replace);

4) Verwenden von replaceAll (Fall 1)

int replaceAll = testString.replaceAll("[^.]", "").length();
System.out.println("replaceAll = " + replaceAll);

5) Verwenden von replaceAll (Fall 2)

int replaceAllCase2 = testString.length() - testString.replaceAll("\\.", "").length();
System.out.println("replaceAll (second case) = " + replaceAllCase2);

6) Split verwenden

int split = testString.split("\\.",-1).length-1;
System.out.println("split = " + split);

7) Verwenden von Java8 (Fall 1)

long java8 = testString.chars().filter(ch -> ch =='.').count();
System.out.println("java8 = " + java8);

8) Die Verwendung von Java8 (Fall 2) ist für Unicode möglicherweise besser als für Fall 1

long java8Case2 = testString.codePoints().filter(ch -> ch =='.').count();
System.out.println("java8 (second case) = " + java8Case2);

9) Verwenden von StringTokenizer

int stringTokenizer = new StringTokenizer(" " +testString + " ", ".").countTokens()-1;
System.out.println("stringTokenizer = " + stringTokenizer);

Aus dem Kommentar : Seien Sie vorsichtig mit dem StringTokenizer, für abcd funktioniert es, aber für a ... bc ... d oder ... abcd oder a .... b ...... c ..... d ... oder etc. es wird nicht funktionieren. Es wird nur zählen. zwischen Zeichen nur einmal

Mehr Infos in Github

Leistungstest (mit JMH , mode = AverageTime, 0.010besser abschneiden als 0.351):

Benchmark              Mode  Cnt  Score    Error  Units
1. countMatches        avgt    5  0.010 ±  0.001  us/op
2. countOccurrencesOf  avgt    5  0.010 ±  0.001  us/op
3. stringTokenizer     avgt    5  0.028 ±  0.002  us/op
4. java8_1             avgt    5  0.077 ±  0.005  us/op
5. java8_2             avgt    5  0.078 ±  0.003  us/op
6. split               avgt    5  0.137 ±  0.009  us/op
7. replaceAll_2        avgt    5  0.302 ±  0.047  us/op
8. replace             avgt    5  0.303 ±  0.034  us/op
9. replaceAll_1        avgt    5  0.351 ±  0.045  us/op
Viacheslav Vedenin
quelle
Die gedruckten Zeichenfolgen stimmen nicht mit den oben genannten überein, und die Reihenfolge ist zuerst am schnellsten, was die Suche zumindest schwierig macht. Schöne Antwort anders!
Maarten Bodewes
Fall 2, verallgemeinert für Codepunkte, die mehr als eine UTF-16- "1🚲2🚲3 has 2".codePoints().filter((c) -> c == "🚲".codePointAt(0)).count()
Codeeinheit
174

Früher oder später muss sich etwas wiederholen. Es ist für Sie viel einfacher, die (sehr einfache) Schleife zu schreiben, als etwas zu verwenden, splitdas viel leistungsfähiger ist als Sie benötigen.

Kapselung der Schleife auf jeden Fall in einer separaten Methode, z

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

Dann brauchen Sie die Schleife nicht in Ihrem Hauptcode - aber die Schleife muss irgendwo da sein.

Jon Skeet
quelle
5
für (int i = 0, l = haystack.length (); i <l; i ++) sei freundlich zu deinem Stapel
Chris
12
(Ich bin mir nicht einmal sicher, woher das "Stapel" -Bit des Kommentars kommt. Es ist nicht so, dass diese Antwort meine rekursive ist, was für den Stapel in der Tat böse ist.)
Jon Skeet
2
Nicht nur das, sondern dies ist möglicherweise eine Anti-Optimierung, ohne einen Blick darauf zu werfen, was der Jit macht. Wenn Sie das oben genannte Beispiel beispielsweise für eine Array-for-Schleife ausgeführt haben, können Sie die Situation verschlimmern.
ShuggyCoUk
4
@sulai: Chris 'Besorgnis ist unbegründet, IMO, angesichts einer trivialen JIT-Optimierung. Gibt es einen Grund, warum dieser Kommentar Ihre Aufmerksamkeit im Moment über drei Jahre später auf sich gezogen hat? Nur interessiert.
Jon Skeet
1
Wahrscheinlich ist @sulai gerade so auf die Frage gestoßen wie ich (während ich mich gefragt habe, ob Java eine integrierte Methode dafür hat) und habe die Daten nicht bemerkt. Ich bin aber gespannt , wie der bewegliche length()Anruf außerhalb der Schleife könnte Leistung machen schlimmer , wie oben von @ShuggyCoUk ein paar Bemerkungen erwähnt.
JKillian
63

Ich hatte eine ähnliche Idee wie Mladen, aber das Gegenteil ...

String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);
PhiLho
quelle
Richtig. ReplaceAll (".") Ersetzt jedes Zeichen, nicht nur einen Punkt. ReplaceAll ("\\.") Hätte funktioniert. Ihre Lösung ist einfacher.
VonC
jjnguy hatte tatsächlich zuerst ein replaceAll ("[^.]") vorgeschlagen, als er meine "abcd" .split ("\\."). length-1-Lösung sah. Aber nachdem ich 5 Mal getroffen wurde, habe ich meine Antwort (und seinen Kommentar) gelöscht.
VonC
"... jetzt hast du zwei Probleme" (obligatorisch) Wie auch immer, ich würde wetten, dass es Dutzende von Schleifen gibt, die in replaceAll()und ausgeführt werden length(). Nun, wenn es nicht sichtbar ist, existiert es nicht; o)
Piskvor verließ das Gebäude
2
Ich denke nicht, dass es eine gute Idee ist, Regex zu verwenden und eine neue Zeichenfolge für das Zählen zu erstellen. Ich würde nur eine statische Methode erstellen, die jedes Zeichen in der Zeichenfolge schleift, um die Zahl zu zählen.
Mingfai
1
@mingfai: in der Tat, aber die ursprüngliche Frage betrifft die Herstellung eines Einzeilers und sogar ohne Schleife (Sie können eine Schleife in einer Zeile erstellen, aber es wird hässlich!). Frage die Frage, nicht die Antwort ... :-)
PhiLho
37
String s = "a.b.c.d";
int charCount = s.length() - s.replaceAll("\\.", "").length();

ReplaceAll (".") Würde alle Zeichen ersetzen.

Die Lösung von PhiLho verwendet ReplaceAll ("[^.]", ""), Das nicht maskiert werden muss, da [.] Das Zeichen 'Punkt' und nicht 'irgendein Zeichen' darstellt.

Mladen Prajdic
quelle
Ich mag diesen. Natürlich gibt es dort immer noch eine Schleife, wie es sein muss.
Der archetypische Paul
Hinweis: Sie müssten diese Zahl teilen, wenn Sie nach
Teilzeichenfolgen mit
30

Meine "idiomatische Einzeiler" -Lösung:

int count = "a.b.c.d".length() - "a.b.c.d".replace(".", "").length();

Haben Sie keine Ahnung, warum eine Lösung, die StringUtils verwendet, akzeptiert wird.

mlchen850622
quelle
4
Es gibt eine ältere Lösung, die dieser in diesem Beitrag ähnlich ist.
JCalcines
7
Weil diese Lösung wirklich ineffizient ist
András
Dadurch wird eine zusätzliche Zeichenfolge erstellt, um eine Zählung zu erstellen. Keine Ahnung, warum jemand dies StringUtils vorziehen würde, wenn StringUtils eine Option ist. Wenn dies keine Option ist, sollten sie einfach eine einfache for-Schleife in einer Utility-Klasse erstellen.
Crush
28
String s = "a.b.c.d";
long result = s.chars().filter(ch -> ch == '.').count();
Fubo
quelle
1
Stimmen Sie + für eine native Lösung.
Scadge
24

Ein kürzeres Beispiel ist

String text = "a.b.c.d";
int count = text.split("\\.",-1).length-1;
Peter Lawrey
quelle
3
Dieser scheint einen relativ großen Overhead zu haben, seien Sie gewarnt, dass er viele kleine Zeichenketten erzeugen kann. Normalerweise ist das nicht wichtig, aber vorsichtig verwenden.
Maarten Bodewes
19

Hier ist eine Lösung ohne Schleife:

public static int countOccurrences(String haystack, char needle, int i){
    return ((i=haystack.indexOf(needle, i)) == -1)?0:1+countOccurrences(haystack, needle, i+1);}


System.out.println("num of dots is "+countOccurrences("a.b.c.d",'.',0));

Nun, es gibt eine Schleife, aber sie ist unsichtbar :-)

- Yonatan

Yonatan Maman
quelle
2
Wenn Ihre Zeichenfolge nicht so lang ist, erhalten Sie einen OutOfMemoryError.
Spencer Kormos
Das Problem klingt so konstruiert, dass es Hausaufgaben sind, und wenn ja, ist diese Rekursion wahrscheinlich die Antwort, nach der Sie gefragt werden.
Erickson
Das verwendet indexOf, das sich wiederholt ... aber eine nette Idee. Eine wirklich "nur rekursive" Lösung in einer Minute veröffentlichen ...
Jon Skeet
Wenn es mehr Vorkommen als Ihre verfügbaren Stapelsteckplätze gibt, haben Sie eine Stapelüberlaufausnahme;)
Luca C.
15

Ich mag die Idee nicht, einen neuen String für diesen Zweck zuzuweisen. Und da der String bereits ein char-Array auf der Rückseite hat, in dem er seinen Wert speichert, ist String.charAt () praktisch kostenlos.

for(int i=0;i<s.length();num+=(s.charAt(i++)==delim?1:0))

erledigt den Trick ohne zusätzliche Zuordnungen, die in einer Zeile oder weniger erfasst werden müssen, mit nur J2SE.

0xCAFEBABE
quelle
Geben Sie etwas Liebe für diesen, weil es der einzige ist, der einen einzigen Durchgang über die Saite macht. Leistung ist mir wichtig.
Javadba
1
charAtiteriert durch 16-Bit-Codepunkte, nicht durch Zeichen! A charin Java ist kein Zeichen. Diese Antwort impliziert also, dass es kein Unicode-Symbol geben darf, wobei ein hoher Ersatz gleich dem Codepunkt von ist delim. Ich bin nicht sicher, ob es für den Punkt korrekt ist, aber im Allgemeinen ist es möglicherweise nicht korrekt.
22.
14

Okay, inspiriert von Yonatans Lösung, hier ist eine, die rein rekursiv ist - die einzigen verwendeten Bibliotheksmethoden sind length()und charAt(), von denen keine eine Schleife ausführt:

public static int countOccurrences(String haystack, char needle)
{
    return countOccurrences(haystack, needle, 0);
}

private static int countOccurrences(String haystack, char needle, int index)
{
    if (index >= haystack.length())
    {
        return 0;
    }

    int contribution = haystack.charAt(index) == needle ? 1 : 0;
    return contribution + countOccurrences(haystack, needle, index+1);
}

Ob Rekursion als Schleife zählt, hängt davon ab, welche genaue Definition Sie verwenden, aber sie ist wahrscheinlich so nah wie möglich.

Ich weiß nicht, ob die meisten JVMs heutzutage eine Schwanzrekursion durchführen ... wenn nicht, erhalten Sie natürlich den gleichnamigen Stapelüberlauf für entsprechend lange Zeichenfolgen.

Jon Skeet
quelle
Nein, die Schwanzrekursion wird wahrscheinlich in Java 7 sein, ist aber noch nicht weit verbreitet. Diese einfache, direkte Schwanzrekursion könnte zur Kompilierungszeit in eine Schleife übersetzt werden, aber das Java 7-Material ist tatsächlich in die JVM integriert, um die Verkettung mit verschiedenen Methoden zu handhaben.
Erickson
3
Es ist wahrscheinlicher, dass Sie eine Schwanzrekursion erhalten, wenn Ihre Methode einen Aufruf an sich selbst zurückgibt (einschließlich eines laufenden Gesamtparameters), als das Ergebnis einer Addition zurückzugeben.
Stephen Denne
12

Inspiriert von Jon Skeet, einer Non-Loop-Version, die Ihren Stack nicht sprengt. Auch ein nützlicher Ausgangspunkt, wenn Sie das Fork-Join-Framework verwenden möchten.

public static int countOccurrences(CharSequeunce haystack, char needle) {
    return countOccurrences(haystack, needle, 0, haystack.length);
}

// Alternatively String.substring/subsequence use to be relatively efficient
//   on most Java library implementations, but isn't any more [2013].
private static int countOccurrences(
    CharSequence haystack, char needle, int start, int end
) {
    if (start == end) {
        return 0;
    } else if (start+1 == end) {
        return haystack.charAt(start) == needle ? 1 : 0;
    } else {
        int mid = (end+start)>>>1; // Watch for integer overflow...
        return
            countOccurrences(haystack, needle, start, mid) +
            countOccurrences(haystack, needle, mid, end);
    }
}

(Haftungsausschluss: Nicht getestet, nicht kompiliert, nicht sinnvoll.)

Vielleicht die beste Möglichkeit (Single-Threaded, keine Ersatzpaar-Unterstützung), es zu schreiben:

public static int countOccurrences(String haystack, char needle) {
    int count = 0;
    for (char c : haystack.toCharArray()) {
        if (c == needle) {
           ++count;
        }
    }
    return count;
}
Tom Hawtin - Tackline
quelle
11

Ich bin mir nicht sicher, wie effizient dies ist, aber es ist der kürzeste Code, den ich schreiben kann, ohne Bibliotheken von Drittanbietern einzubringen:

public static int numberOf(String target, String content)
{
    return (content.split(target).length - 1);
}
KannedFarU
quelle
4
Um auch Vorkommen am Ende der Zeichenfolge zu zählen, müssen Sie split mit einem negativen Limit-Argument wie dem folgenden aufrufen : return (content.split(target, -1).length - 1);. Standardmäßig werden Vorkommen am Ende der Zeichenfolge im Array weggelassen, die sich aus split () ergeben. Siehe die Doku
vlz
10

Mit Sie können auch Streams verwenden, um dies zu erreichen. Natürlich gibt es eine Iteration hinter den Kulissen, aber Sie müssen sie nicht explizit schreiben!

public static long countOccurences(String s, char c){
    return s.chars().filter(ch -> ch == c).count();
}

countOccurences("a.b.c.d", '.'); //3
countOccurences("hello world", 'l'); //3
Alexis C.
quelle
Die Verwendung von .codePoints()anstelle von .chars()würde dann jeden Unicode-Wert unterstützen (einschließlich derer, die Ersatzpaare erfordern)
Luke Usherwood
10

Es ist auch möglich, redu in Java 8 zu verwenden, um dieses Problem zu lösen:

int res = "abdsd3$asda$asasdd$sadas".chars().reduce(0, (a, c) -> a + (c == '$' ? 1 : 0));
System.out.println(res);

Ausgabe:

3
gil.fernandes
quelle
8

Komplette Probe:

public class CharacterCounter
{

  public static int countOccurrences(String find, String string)
  {
    int count = 0;
    int indexOf = 0;

    while (indexOf > -1)
    {
      indexOf = string.indexOf(find, indexOf + 1);
      if (indexOf > -1)
        count++;
    }

    return count;
  }
}

Anruf:

int occurrences = CharacterCounter.countOccurrences("l", "Hello World.");
System.out.println(occurrences); // 3
Benny Neugebauer
quelle
falscher Code funktioniert nicht, wenn ich versuche, int Vorkommen = CharacterCounter.countOccurrences ("1", "101"); System.out.println (Vorkommen); // 1
Jayesh
Ich begebe einen Fix für den Code, der mit der gleichen Logik
funktioniert
8

Der einfachste Weg, um die Antwort zu erhalten, ist wie folgt:

public static void main(String[] args) {
    String string = "a.b.c.d";
    String []splitArray = string.split("\\.",-1);
    System.out.println("No of . chars is : " + (splitArray.length-1));
}
Amar Magar
quelle
2
Dieses Snippet gibt nicht die richtige Anzahl von Punkten für eine gegebene Eingabe "abc" zurück
dekaru
@dekaru Könnten Sie bitte Ihren Stich in den Kommentar einfügen, damit wir einen Blick darauf werfen können.
Amar Magar
5

Wenn Sie das Spring-Framework verwenden, können Sie auch die Klasse "StringUtils" verwenden. Die Methode wäre "countOccurrencesOf".

user496208
quelle
5

Sie können die split()Funktion in nur einem Zeilencode verwenden

int noOccurence=string.split("#",-1).length-1;
user3322553
quelle
Split erstellt wirklich das Array von Zeichenfolgen, was viel Zeit in Anspruch nimmt.
Palec
Du hast recht, das ist ein echtes Problem. Auf andere Weise wird vermieden, dass eine Drittanbieter-Bibliothek in Ihr Projekt aufgenommen wird (falls noch nicht geschehen). Dies hängt davon ab, was Sie tun möchten und wie hoch die Leistungserwartung ist.
Benj
3
Diese Lösung enthält NICHT die nachfolgenden leeren Treffer, da das Argument limitin diesem überladenen Split-Methodenaufruf auf Null gesetzt wird. Ein Beispiel: Es "1##2#3#####".split("#")wird nur ein Array der Größe 4 ( [0:"1";1:""; 2:"2"; 3:"3"]) anstelle der Größe 9 ( [0:"1"; 1:""; 2:"2"; 3:"3"; 4:""; 5:""; 6:""; 7:""; 8:""]) ausgegeben.
Klaar
4
public static int countOccurrences(String container, String content){
    int lastIndex, currIndex = 0, occurrences = 0;
    while(true) {
        lastIndex = container.indexOf(content, currIndex);
        if(lastIndex == -1) {
            break;
        }
        currIndex = lastIndex + content.length();
        occurrences++;
    }
    return occurrences;
}
Am schwierigsten
quelle
4
import java.util.Scanner;

class apples {

    public static void main(String args[]) {    
        Scanner bucky = new Scanner(System.in);
        String hello = bucky.nextLine();
        int charCount = hello.length() - hello.replaceAll("e", "").length();
        System.out.println(charCount);
    }
}//      COUNTS NUMBER OF "e" CHAR´s within any string input
kassim
quelle
3

Während Methoden es ausblenden können, gibt es keine Möglichkeit, ohne eine Schleife (oder Rekursion) zu zählen. Sie möchten jedoch aus Leistungsgründen ein char [] verwenden.

public static int count( final String s, final char c ) {
  final char[] chars = s.toCharArray();
  int count = 0;
  for(int i=0; i<chars.length; i++) {
    if (chars[i] == c) {
      count++;
    }
  }
  return count;
}

Die Verwendung von replaceAll (das ist RE) klingt nicht nach dem besten Weg.

tcurdt
quelle
Ich denke, das ist die eleganteste Lösung. Warum haben Sie toCharArray verwendet und nicht direkt charAt?
Panayotis
Das Schleifen mit charAt war früher zumindest langsamer. Könnte auch von der Plattform abhängen. Der einzige Weg, dies wirklich herauszufinden, wäre, den Unterschied zu messen.
tcurdt
3

Nun, mit einer ganz ähnlichen Aufgabe bin ich auf diesen Thread gestoßen. Ich habe keine Einschränkung der Programmiersprache festgestellt und da groovy auf einem Java-VM ausgeführt wird: So konnte ich mein Problem mit Groovy lösen.

"a.b.c.".count(".")

erledigt.

Christoph Zabinski
quelle
3

Eine viel einfachere Lösung wäre, die Zeichenfolge nur anhand des Zeichens zu teilen, mit dem Sie sie abgleichen.

Zum Beispiel,

int getOccurences(String characters, String string) { String[] words = string.split(characters); return words.length - 1; }

Dies ergibt 4 im Fall von: getOccurences("o", "something about a quick brown fox");

Saharkasmus
quelle
Das Problem hierbei ist, dass ein Array zugewiesen werden muss, was sehr langsam ist.
Palec
2

Irgendwo im Code muss sich etwas wiederholen. Der einzige Weg, dies zu umgehen, ist ein vollständiges Abrollen der Schleife:

int numDots = 0;
if (s.charAt(0) == '.') {
    numDots++;
}

if (s.charAt(1) == '.') {
    numDots++;
}


if (s.charAt(2) == '.') {
    numDots++;
}

... usw., aber dann sind Sie derjenige, der die Schleife manuell im Quellcode-Editor ausführt - anstelle des Computers, auf dem sie ausgeführt wird. Siehe den Pseudocode:

create a project
position = 0
while (not end of string) {
    write check for character at position "position" (see above)
}
write code to output variable "numDots"
compile program
hand in homework
do not think of the loop that your "if"s may have been optimized and compiled to
Piskvor verließ das Gebäude
quelle
2

Hier ist eine etwas andere Rekursionslösung:

public static int countOccurrences(String haystack, char needle)
{
    return countOccurrences(haystack, needle, 0);
}

private static int countOccurrences(String haystack, char needle, int accumulator)
{
    if (haystack.length() == 0) return accumulator;
    return countOccurrences(haystack.substring(1), needle, haystack.charAt(0) == needle ? accumulator + 1 : accumulator);
}
Stephen Denne
quelle
2

Warum nicht einfach das Zeichen teilen und dann die Länge des resultierenden Arrays ermitteln? Die Array-Länge ist immer die Anzahl der Instanzen + 1. Richtig?

Darryl Preis
quelle
2

Der folgende Quellcode gibt Ihnen die Anzahl der Vorkommen einer bestimmten Zeichenfolge in einem vom Benutzer eingegebenen Wort an: -

import java.util.Scanner;

public class CountingOccurences {

    public static void main(String[] args) {

        Scanner inp= new Scanner(System.in);
        String str;
        char ch;
        int count=0;

        System.out.println("Enter the string:");
        str=inp.nextLine();

        while(str.length()>0)
        {
            ch=str.charAt(0);
            int i=0;

            while(str.charAt(i)==ch)
            {
                count =count+i;
                i++;
            }

            str.substring(count);
            System.out.println(ch);
            System.out.println(count);
        }

    }
}
Shubham
quelle
2
int count = (line.length() - line.replace("str", "").length())/"str".length();
Shaban
quelle