web-dev-qa-db-de.com

Anzahl der Vorkommen von Teilzeichenfolgen in Zeichenfolge in Swift

Meine Hauptsaite ist "Hallo Swift Swift und Swift" und die Teilzeichenfolge ist Swift . Ich muss die Anzahl der Male ermitteln, in denen die Teilzeichenfolge "Swift" in der genannten Zeichenfolge auftritt.

Dieser Code kann bestimmen, ob das Muster existiert.

var string = "hello Swift Swift and Swift"

if string.rangeOfString("Swift") != nil {
    println("exists")
}

Jetzt muss ich die Anzahl des Vorkommens kennen.

29
Reza

Ein einfacher Ansatz wäre, sich von "Swift" abzuspalten und 1 von der Anzahl der Teile abzuziehen:

let s = "hello Swift Swift and Swift"
let tok =  s.components(separatedBy:"Swift")
print(tok.count-1)

Dieser Code druckt 3.

Edit: Before Swift 3-Syntax Der Code sah folgendermaßen aus:

let tok =  s.componentsSeparatedByString("Swift")
71
dasblinkenlight

Ich würde eine Erweiterung zu String in Swift 3 empfehlen, zum Beispiel:

extension String {
    func countInstances(of stringToFind: String) -> Int {
        var stringToSearch = self
        var count = 0
        while let foundRange = stringToSearch.range(of: stringToFind, options: .diacriticInsensitive) {
            stringToSearch = stringToSearch.replacingCharacters(in: foundRange, with: "")
            count += 1
        }
        return count
    }
}

Es ist eine Schleife, die jede Instanz von stringToFind findet und entfernt, wodurch die Anzahl bei jeder Umlaufzeit erhöht wird. Wenn der searchString kein stringToFind mehr enthält, bricht die Schleife und der Count geht zurück.

Beachten Sie, dass ich .diacriticInsensitive verwende, um Akzente zu ignorieren (beispielsweise würden Lebenslauf und Lebenslauf gefunden). Möglicherweise möchten Sie die Optionen in Abhängigkeit von den zu suchenden Zeichenfolgentypen hinzufügen oder ändern.

14
dwsolberg

Optimierung der dwsolbergs Lösung schneller zählen. Auch schneller als componentsSeparatedByString.

extension String {
    /// stringToFind must be at least 1 character.
    func countInstances(of stringToFind: String) -> Int {
        assert(!stringToFind.isEmpty)
        var count = 0
        var searchRange: Range<String.Index>?
        while let foundRange = range(of: stringToFind, options: [], range: searchRange) {
            count += 1
            searchRange = Range(uncheckedBounds: (lower: foundRange.upperBound, upper: endIndex))
        }
        return count
    }
}

Verwendungszweck:

// return 2
"aaaa".countInstances(of: "aa")
  • Wenn Sie Akzente ignorieren möchten, können Sie options: [] durch options: .diacriticInsensitive wie bei dwsolbergs ersetzen.
  • Wenn Sie den Fall ignorieren möchten, können Sie options: [] durch options: .caseInsensitive ersetzen, wie von ConfusionTowers vorgeschlagen.
  • Wenn Sie sowohl Akzente als auch Groß- und Kleinschreibung ignorieren möchten, können Sie options: [] durch options: [.caseInsensitive, .diacriticInsensitive] ersetzen, wie von ConfusionTowers vorgeschlagen.
11
Cœur

Wenn Sie Zeichen anstelle von Teilzeichenfolgen zählen möchten:

extension String {
    func count(of needle: Character) -> Int {
        return reduce(0) {
            $1 == needle ? $0 + 1 : $0
        }
    }
}
7
mxcl

Ich brauchte eine Möglichkeit, Teilzeichenfolgen zu zählen, die den Beginn der nächsten übereinstimmenden Teilzeichenfolge enthalten können. Verwendung von dwsolbergs extension und Strings range (of: options: range: locale :) method Ich kam mit dieser String-Erweiterung auf

extension String
{
    /**
     Counts the occurrences of a given substring by calling Strings `range(of:options:range:locale:)` method multiple times.

     - Parameter substring : The string to search for, optional for convenience

     - Parameter allowOverlap : Bool flag indicating whether the matched substrings may overlap. Count of "????????" in "????????????????" is 2 if allowOverlap is **false**, and 3 if it is **true**

     - Parameter options : String compare-options to use while counting

     - Parameter range : An optional range to limit the search, default is **nil**, meaning search whole string

     - Parameter locale : Locale to use while counting

     - Returns : The number of occurrences of the substring in this String
     */
    public func count(
        occurrencesOf substring: String?,
        allowOverlap: Bool = false,
        options: String.CompareOptions = [],
        range searchRange: Range<String.Index>? = nil,
        locale: Locale? = nil) -> Int
    {
        guard let substring = substring, !substring.isEmpty else { return 0 }

        var count = 0

        let searchRange = searchRange ?? startIndex..<endIndex

        var searchStartIndex = searchRange.lowerBound
        let searchEndIndex = searchRange.upperBound

        while let rangeFound = range(of: substring, options: options, range: searchStartIndex..<searchEndIndex, locale: locale)
        {
            count += 1

            if allowOverlap
            {
                searchStartIndex = index(rangeFound.lowerBound, offsetBy: 1)
            }
            else
            {
                searchStartIndex = rangeFound.upperBound
            }
        }

        return count
    }
}
3

Versuche dies

var mainString = "hello Swift Swift and Swift"
var count = 0

mainString.enumerateSubstrings(in: mainString.startIndex..<mainString.endIndex, options: .byWords) { (subString, subStringRange, enclosingRange, stop) in

    if case let s? = subString{

        if s.caseInsensitiveCompare("Swift") == .orderedSame{
            count += 1
        }
    }


}

print(count)