1064 Stimmen

Wie würden Sie das Vorkommen einer Zeichenkette (eigentlich eines Zeichens) innerhalb einer Zeichenkette zählen?

Ich mache gerade etwas, bei dem ich merke, dass ich zählen möchte, wie viele / s, die ich in einer Zeichenkette finden konnte, und dann fiel mir auf, dass es mehrere Möglichkeiten gab, aber ich konnte mich nicht entscheiden, welche die beste (oder einfachste) war.

Im Moment denke ich an so etwas wie:

string source = "/once/upon/a/time/";
int count = source.Length - source.Replace("/", "").Length;

Aber es gefällt mir überhaupt nicht, hat jemand Lust?

Ich möchte nicht wirklich etwas ausgraben. RegEx oder doch?

Ich weiß, dass meine Zeichenfolge den gesuchten Begriff enthalten wird, also können Sie davon ausgehen, dass...

Natürlich auch für Streicher wobei Länge > 1 ,

string haystack = "/once/upon/a/time";
string needle = "/";
int needleCount = ( haystack.Length - haystack.Replace(needle,"").Length ) / needle.Length;

78voto

tsionyx Punkte 1545

Ich habe einige Nachforschungen angestellt und festgestellt, dass Richard Watson's Lösung ist in den meisten Fällen am schnellsten. Das ist die Tabelle mit den Ergebnissen aller Lösungen in diesem Beitrag (außer denen, die Regex weil es beim Parsen von Strings wie "test{test") zu Ausnahmen kommt

    Name      | Short/char |  Long/char | Short/short| Long/short |  Long/long |
    Inspite   |         134|        1853|          95|        1146|         671|
    LukeH_1   |         346|        4490|         N/A|         N/A|         N/A|
    LukeH_2   |         152|        1569|         197|        2425|        2171|
Bobwienholt   |         230|        3269|         N/A|         N/A|         N/A|
Richard Watson|          33|         298|         146|         737|         543|
StefanosKargas|         N/A|         N/A|         681|       11884|       12486|

Sie sehen, dass der ursprüngliche Algorithmus bevorzugt wird, wenn es darum geht, die Anzahl der Vorkommen von kurzen Teilstrings (1-5 Zeichen) in kurzen Strings (10-50 Zeichen) zu finden.

Außerdem sollten Sie für mehrstellige Teilzeichenfolgen den folgenden Code verwenden (basierend auf Richard Watson's Lösung)

int count = 0, n = 0;

if(substring != "")
{
    while ((n = source.IndexOf(substring, n, StringComparison.InvariantCulture)) != -1)
    {
        n += substring.Length;
        ++count;
    }
}

64voto

Richard Watson Punkte 2544
string source = "/once/upon/a/time/";
int count = 0;
int n = 0;

while ((n = source.IndexOf('/', n)) != -1)
{
   n++;
   count++;
}

Auf meinem Computer ist es etwa 2 Sekunden schneller als die Lösung für jedes Zeichen bei 50 Millionen Iterationen.

Überarbeitung 2013:

Ändern Sie die Zeichenfolge in ein char[] und durchlaufen Sie es. Spart weitere ein oder zwei Sekunden von der Gesamtzeit für 50m Iterationen!

char[] testchars = source.ToCharArray();
foreach (char c in testchars)
{
     if (c == '/')
         count++;
}

Das geht noch schneller:

char[] testchars = source.ToCharArray();
int length = testchars.Length;
for (int n = 0; n < length; n++)
{
    if (testchars[n] == '/')
        count++;
}

Die Iteration vom Ende des Arrays bis 0 scheint am schnellsten zu sein, nämlich um etwa 5 %.

int length = testchars.Length;
for (int n = length-1; n >= 0; n--)
{
    if (testchars[n] == '/')
        count++;
}

Ich habe mich gefragt, warum das so sein könnte und habe herumgegoogelt (ich erinnere mich an etwas über die umgekehrte Iteration, die schneller ist), und bin auf diese SO-Frage gestoßen, die ärgerlicherweise bereits die Technik string to char[] verwendet. Ich denke, die Umkehrung Trick ist neu in diesem Zusammenhang, obwohl.

Was ist der schnellste Weg, um durch einzelne Zeichen in einer Zeichenfolge in C# zu iterieren?

49voto

ZombieSheep Punkte 29085

Beide funktionieren nur bei Suchbegriffen, die nur aus einem Zeichen bestehen...

countOccurences("the", "the answer is the answer");

int countOccurences(string needle, string haystack)
{
    return (haystack.Length - haystack.Replace(needle,"").Length) / needle.Length;
}

kann sich bei längeren Nadeln als besser erweisen...

Aber es muss doch einen eleganteren Weg geben :)

22voto

Brian Rudolph Punkte 5862

Bearbeiten:

source.Split('/').Length-1

21voto

cederlof Punkte 6841
Regex.Matches(input,  Regex.Escape("stringToMatch")).Count

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X