2016-04-26 14 views
0

Ich habe eine Zeichenfolge zum Beispiel "ab ad adk fda kla kad ab ab kd". Ich möchte alle Bereich von ab bekommen. (Hier ist ab an 3 Position, so dass ich 3 Bereich erhalten sollte). In normalen Szenario funktioniert mein Code gut, aber wenn Suchtext ist ".", Dann bekomme ich falsches Ergebnisbekomme alle Bereiche eines Teilstrings in einer Zeichenfolge in swift

do { 
    let regEx = try NSRegularExpression(pattern: searchText, options: NSRegularExpressionOptions.CaseInsensitive) 

    let matchesRanges = regEx.matchesInString(attributedText.string, options:[], range: NSMakeRange(0, attributedText.string.length)) 

    for rng in matchesRanges { 
     let wordRange = rng.rangeAtIndex(0) 
    } 
} catch { 
    ... 
} 
+0

Sie müssen zeigen, was Sie versucht haben, und erklären, was es falsch macht – Wain

+0

bitte erklären Sie im Detail, welches Ergebnis Sie wollen? – PSS

+0

Ein '.' ist ein Sonderzeichen, das 'Jedes Zeichen' bedeutet. – redent84

Antwort

0

Sie können für bestimmte Zeichenfolge durch folgenden Code zählen erhalten Vorkommen:

let str: NSMutableString = "ab ad adk fda kla kad ab ab kd" 
let count = str.replaceOccurrencesOfString("ab", withString: "ab", options: NSStringCompareOptions.LiteralSearch, range: NSMakeRange(0, str.length)) 
+0

Nein Ich möchte die Bereiche erhalten, so dass Attribute auf diese Bereiche angewendet werden können. –

2

ich würde eine solche Lösung vorschlagen:

import Foundation 

extension String { 

    func rangesOfString(s: String) -> [Range<Index>] { 
     let re = try! NSRegularExpression(pattern: NSRegularExpression.escapedPatternForString(s), options: []) 
     return re.matchesInString(self, options: [], range: nsRange(startIndex ..< endIndex)).flatMap { range($0.range) } 
    } 

    func range(nsRange : NSRange) -> Range<Index>? { 
     let utf16from = utf16.startIndex.advancedBy(nsRange.location, limit: utf16.endIndex) 
     let utf16to = utf16from.advancedBy(nsRange.length, limit: utf16.endIndex) 

     if let from = String.Index(utf16from, within: self), 
      let to = String.Index(utf16to, within: self) 
     { 
      return from ..< to 
     } else { 
      return nil 
     } 
    } 

    func nsRange(range : Range<Index>) -> NSRange { 
     let utf16from = String.UTF16View.Index(range.startIndex, within: utf16) 
     let utf16to = String.UTF16View.Index(range.endIndex, within: utf16) 
     return NSRange(location: utf16.startIndex.distanceTo(utf16from), length: utf16from.distanceTo(utf16to)) 
    } 

} 

print("[^x]? [^x]? [^x]?".rangesOfString("[^x]?")) // [Range(0..<5), Range(6..<11), Range(12..<17)] 

Neben der Hauptfrage, dieser Code zeigt auch die Art und Weise umwandeln NSRange zu und von Range<String.Index> (basierend auf this post).

+0

Passt es auf alle anderen Sonderzeichen auf? –

+0

Ich benutze [NSRegularExpression.escapedPatternForString()] (https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSRegularExpression_Class/#//apple_ref/occ/clm/NSRegularExpression/escapedPatternForString :), um irgendwelche zu entkommen mögliche Muster-Metazeichen. Dies muss eine zuverlässige Lösung sein. – werediver

+0

Diese Range <-> NSRange Konvertierungen sehen vertraut http://StackOverflow.com/A/30404532/1187415 :) –

1

Sie verwenden reguläre Ausdrücke, Sie müssen also auf Zeichen achten, die eine besondere Bedeutung haben - . ist nur eine davon.

Wenn Sie eine Suche nach Teil tun, schlage ich vor, die gute alte gängiges Portfolio zu verwenden ... Methoden statt:

func rangeOfString(_ searchString: String, 
      options mask: NSStringCompareOptions, 
      range searchRange: NSRange) -> NSRange 

Denken Sie, dass die Methode auf dem String aufrufen (und stellen Sie die searchRange), bis keine weiteren Übereinstimmungen gefunden werden.

2

Die folgende Lösung verwendet die nativen Swift 4 Funktion range(of:, options:, range:, locale:)):

extension String { 
    func ranges(of substring: String, options: CompareOptions = [], locale: Locale? = nil) -> [Range<Index>] { 
     var ranges: [Range<Index>] = [] 
     while let range = self.range(of: substring, options: options, range: (ranges.last?.upperBound ?? self.startIndex)..<self.endIndex, locale: locale) { 
      ranges.append(range) 
     } 
     return ranges 
    } 
} 

(Swift 4 dann bietet native API von Range<Index> zu NSRange konvertieren)

+0

Dies kann in einigen Situationen zu einer Endlosschleife führen, wenn ein regulärer Ausdruck verwendet wird. Überprüfen Sie diese Antwort auf, wie man es vermeidet https://stackoverflow.com/a/32306142/2303865 –

Verwandte Themen