2017-10-21 57 views
0

Swift 3 introduit String.range(of:options). Puis, avec cette fonction, il est possible correspondre à une partie de la chaîne sans créer un objet NSRegularExpression, par exemple:Sans utiliser NSRegularExpression, Comment puis-je obtenir toutes les correspondances de mon expression régulière de chaîne?

let text = "it is need #match my both #hashtag!" 
let match = text.range(of: "(?:^#|\\s#)[\\p{L}0-9_]*", options: .regularExpression)! 

print(text[match]) // #math 

Mais, est correspondance possible les deux occurrences de l'expression régulière (qui est, #match et #hashtag), au lieu de seulement le premier?

+0

https://stackoverflow.com/questions/32305891/index-of-a-substring-in-a-string-with-swift/32306142#32306142 vous devez mettre en œuvre c'est toi. Vérifiez les gammes de méthodes (de :) comment j'ai accompli cela –

+0

@LeoDabus Je suis à la recherche d'une solution de vanille, sans extension ou sur-ingénierie. Mon cas est simple, et je vais l'utiliser dans une situation. Mais merci. – Macabeus

+0

Si vous souhaitez utiliser cette méthode, vous n'avez pas d'autre choix que de l'implémenter vous-même. –

Répondre

1
let text = "it is need #match my both #hashtag!" 
// create an object to store the ranges found 
var ranges: [Range<String.Index>] = [] 
// create an object to store your search position 
var start = text.startIndex 
// create a while loop to find your regex ranges 
while let range = text.range(of: "(?:^#|\\s#)[\\p{L}0-9_]*", options: .regularExpression, range: start..<text.endIndex) { 
    // append your range found 
    ranges.append(range) 
    // and change the startIndex of your string search 
    start = range.lowerBound < range.upperBound ? range.upperBound : text.index(range.lowerBound, offsetBy: 1, limitedBy: text.endIndex) ?? text.endIndex 
} 
ranges.forEach({print(text[$0])}) 

Ce imprimera

#match

#hashtag

Si vous avez besoin d'utiliser plus d'une fois dans votre code, vous devez ajouter cette extension à votre projet:

extension String { 
    func ranges(of string: String, options: CompareOptions = .literal) -> [Range<Index>] { 
     var result: [Range<Index>] = [] 
     var start = startIndex 
     while let range = range(of: string, options: options, range: start..<endIndex) { 
      result.append(range) 
      start = range.lowerBound < range.upperBound ? range.upperBound : index(range.lowerBound, offsetBy: 1, limitedBy: endIndex) ?? endIndex 
     } 
     return result 
    } 
} 

utilisation:

let text = "it is need #match my both #hashtag!" 
let pattern = "(?:^#|\\s#)[\\p{L}0-9_]*" 
let ranges = text.ranges(of: pattern, options: .regularExpression) 
let matches = ranges.map{text[$0]} 
print(matches) // [" #match", " #hashtag"] 
+0

Merci! Je ne peux vraiment pas comprendre pourquoi la bibliothèque par défaut n'a pas cette fonction utile. Il a 'range', mais n'a pas' ranges'. – Macabeus

+1

Vous êtes les bienvenus. Au moins, nous pouvons modifier la langue au besoin. Vous pouvez ajouter l'extension de plages à partir du lien que j'ai posté dans votre projet et l'utiliser au besoin. –

+0

Comment cela correspond-il à la regex? Je ne comprends pas comment cela fonctionne. – seaturtle