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;

2voto

bizah Punkte 227
            var conditionalStatement = conditionSetting.Value;

            //order of replace matters, remove == before =, incase of ===
            conditionalStatement = conditionalStatement.Replace("==", "~").Replace("!=", "~").Replace('=', '~').Replace('!', '~').Replace('>', '~').Replace('<', '~').Replace(">=", "~").Replace("<=", "~");

            var listOfValidConditions = new List<string>() { "!=", "==", ">", "<", ">=", "<=" };

            if (conditionalStatement.Count(x => x == '~') != 1)
            {
                result.InvalidFieldList.Add(new KeyFieldData(batch.DECurrentField, "The IsDoubleKeyCondition does not contain a supported conditional statement. Contact System Administrator."));
                result.Status = ValidatorStatus.Fail;
                return result;
            }

Benötigt, um etwas Ähnliches zu tun, um bedingte Anweisungen aus einer Zeichenfolge zu testen.

Ersetzte das Gesuchte durch ein einzelnes Zeichen und zählte die Instanzen des einzelnen Zeichens.

Natürlich muss das einzelne Zeichen, das Sie verwenden, vorher auf Nichtvorhandensein in der Zeichenkette überprüft werden, um falsche Zählungen zu vermeiden.

2voto

Casey Chester Punkte 238

Ich dachte, ich würde meine Erweiterungsmethode in den Ring werfen (siehe Kommentare für weitere Informationen). Ich habe keine formalen Tests durchgeführt, aber ich denke, dass es für die meisten Szenarien sehr schnell sein muss.

EDIT: OK - diese SO-Frage brachte mich dazu, mich zu fragen, wie die Leistung unserer aktuellen Implementierung im Vergleich zu einigen der hier vorgestellten Lösungen abschneiden würde. Ich beschloss, einen kleinen Leistungsvergleich durchzuführen, und stellte fest, dass unsere Lösung sehr gut mit der Leistung der Lösung von Richard Watson bis zu einer aggressiven Suche mit großen Zeichenfolgen (100 Kb +), großen Teilzeichenfolgen (32 Kb +) und vielen eingebetteten Wiederholungen (10K +). An diesem Punkt war unsere Lösung etwa 2- bis 4-mal langsamer. Angesichts dessen und der Tatsache, dass uns die von Richard Watson vorgestellte Lösung sehr gut gefällt, haben wir unsere Lösung entsprechend umgestaltet. Ich wollte dies nur allen zur Verfügung stellen, die davon profitieren könnten.

Unsere ursprüngliche Lösung:

    /// <summary>
    /// Counts the number of occurrences of the specified substring within
    /// the current string.
    /// </summary>
    /// <param name="s">The current string.</param>
    /// <param name="substring">The substring we are searching for.</param>
    /// <param name="aggressiveSearch">Indicates whether or not the algorithm 
    /// should be aggressive in its search behavior (see Remarks). Default 
    /// behavior is non-aggressive.</param>
    /// <remarks>This algorithm has two search modes - aggressive and 
    /// non-aggressive. When in aggressive search mode (aggressiveSearch = 
    /// true), the algorithm will try to match at every possible starting 
    /// character index within the string. When false, all subsequent 
    /// character indexes within a substring match will not be evaluated. 
    /// For example, if the string was 'abbbc' and we were searching for 
    /// the substring 'bb', then aggressive search would find 2 matches 
    /// with starting indexes of 1 and 2. Non aggressive search would find 
    /// just 1 match with starting index at 1. After the match was made, 
    /// the non aggressive search would attempt to make it's next match 
    /// starting at index 3 instead of 2.</remarks>
    /// <returns>The count of occurrences of the substring within the string.</returns>
    public static int CountOccurrences(this string s, string substring, 
        bool aggressiveSearch = false)
    {
        // if s or substring is null or empty, substring cannot be found in s
        if (string.IsNullOrEmpty(s) || string.IsNullOrEmpty(substring))
            return 0;

        // if the length of substring is greater than the length of s,
        // substring cannot be found in s
        if (substring.Length > s.Length)
            return 0;

        var sChars = s.ToCharArray();
        var substringChars = substring.ToCharArray();
        var count = 0;
        var sCharsIndex = 0;

        // substring cannot start in s beyond following index
        var lastStartIndex = sChars.Length - substringChars.Length;

        while (sCharsIndex <= lastStartIndex)
        {
            if (sChars[sCharsIndex] == substringChars[0])
            {
                // potential match checking
                var match = true;
                var offset = 1;
                while (offset < substringChars.Length)
                {
                    if (sChars[sCharsIndex + offset] != substringChars[offset])
                    {
                        match = false;
                        break;
                    }
                    offset++;
                }
                if (match)
                {
                    count++;
                    // if aggressive, just advance to next char in s, otherwise, 
                    // skip past the match just found in s
                    sCharsIndex += aggressiveSearch ? 1 : substringChars.Length;
                }
                else
                {
                    // no match found, just move to next char in s
                    sCharsIndex++;
                }
            }
            else
            {
                // no match at current index, move along
                sCharsIndex++;
            }
        }

        return count;
    }

Und hier ist unsere überarbeitete Lösung:

    /// <summary>
    /// Counts the number of occurrences of the specified substring within
    /// the current string.
    /// </summary>
    /// <param name="s">The current string.</param>
    /// <param name="substring">The substring we are searching for.</param>
    /// <param name="aggressiveSearch">Indicates whether or not the algorithm 
    /// should be aggressive in its search behavior (see Remarks). Default 
    /// behavior is non-aggressive.</param>
    /// <remarks>This algorithm has two search modes - aggressive and 
    /// non-aggressive. When in aggressive search mode (aggressiveSearch = 
    /// true), the algorithm will try to match at every possible starting 
    /// character index within the string. When false, all subsequent 
    /// character indexes within a substring match will not be evaluated. 
    /// For example, if the string was 'abbbc' and we were searching for 
    /// the substring 'bb', then aggressive search would find 2 matches 
    /// with starting indexes of 1 and 2. Non aggressive search would find 
    /// just 1 match with starting index at 1. After the match was made, 
    /// the non aggressive search would attempt to make it's next match 
    /// starting at index 3 instead of 2.</remarks>
    /// <returns>The count of occurrences of the substring within the string.</returns>
    public static int CountOccurrences(this string s, string substring, 
        bool aggressiveSearch = false)
    {
        // if s or substring is null or empty, substring cannot be found in s
        if (string.IsNullOrEmpty(s) || string.IsNullOrEmpty(substring))
            return 0;

        // if the length of substring is greater than the length of s,
        // substring cannot be found in s
        if (substring.Length > s.Length)
            return 0;

        int count = 0, n = 0;
        while ((n = s.IndexOf(substring, n, StringComparison.InvariantCulture)) != -1)
        {
            if (aggressiveSearch)
                n++;
            else
                n += substring.Length;
            count++;
        }

        return count;
    }

2voto

user3090281 Punkte 21

String in String:

Suchen Sie "usw." in " JD JD JD JD usw. und usw. JDJDJDJJDJDJDJDJD und usw."

var strOrigin = " .. JD JD JD JD etc. and etc. JDJDJDJDJDJDJDJD and etc.";
var searchStr = "etc";
int count = (strOrigin.Length - strOrigin.Replace(searchStr, "").Length)/searchStr.Length.

Prüfen Sie die Leistung, bevor Sie sie als unsolide/ungeschickt verwerfen...

2voto

user2011559 Punkte 21
string source = "/once/upon/a/time/";
int count = 0, n = 0;
while ((n = source.IndexOf('/', n) + 1) != 0) count++;

Eine Abwandlung der Antwort von Richard Watson, die etwas schneller und effizienter ist, je öfter das Zeichen in der Zeichenkette vorkommt, und weniger Code benötigt!

Obwohl ich sagen muss, dass ich, ohne jedes Szenario ausgiebig getestet zu haben, eine sehr deutliche Geschwindigkeitsverbesserung durch die Verwendung feststellen konnte:

int count = 0;
for (int n = 0; n < source.Length; n++) if (source[n] == '/') count++;

2voto

Stefanos Kargas Punkte 9553

Eine generische Funktion für das Vorkommen von Zeichenketten:

public int getNumberOfOccurencies(String inputString, String checkString)
{
    if (checkString.Length > inputString.Length || checkString.Equals("")) { return 0; }
    int lengthDifference = inputString.Length - checkString.Length;
    int occurencies = 0;
    for (int i = 0; i < lengthDifference; i++) {
        if (inputString.Substring(i, checkString.Length).Equals(checkString)) { occurencies++; i += checkString.Length - 1; } }
    return occurencies;
}

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