как запустить кратные NSRegularExpression один раз - PullRequest
0 голосов
/ 02 ноября 2018

У меня есть куча NSRegularExpression, и я хочу запустить ее один раз. Кто-нибудь знает, как это сделать?

На данный момент я делаю это в .forEach, по соображениям производительности я не думаю, что это лучшая идея

Каждый NSRegularExpression должен соответствовать разному шаблону, после сопоставления мне нужно иметь дело с каждым разным видом соответствия. Например, если я сопоставляю первое регулярное выражение в моем массиве, мне нужно сделать что-то отличное от второго и т. Д ...

let test: String = "Stuff"
let range: NSRange = // a range

var regexes = [NSRegularExpression] = // all of my regexes
regexes.forEach { $0.matches(in: text, options: [], range: range) }

Спасибо за помощь

1 Ответ

0 голосов
/ 12 ноября 2018

Вы можете оценить несколько регулярных выражений как одно, если объедините их, используя группы захвата и выражения ИЛИ .

Если вы хотите искать: language, Objective-C и Swift строк, вы должны использовать шаблон, подобный этому: (language)|(Objective-C)|(Swift). Каждая группа захвата имеет порядковый номер, поэтому, если в исходной строке найдено language, объект сопоставления предоставляет порядковый номер.

Вы можете использовать код в этом примере игровой площадки:

import Foundation

let sourceString: String = "Swift is a great language to program, but don't forget Objective-C."
let expresions = [ "language",     // Expression 0
                   "Objective-C",  // Expression 1
                   "Swift"         // Expression 2
                 ]
let pattern = expresions
                .map { "(\($0))" }
                .joined(separator: "|") // pattern is defined as : (language)|(Objective-C)|(Swift)

let regex = try? NSRegularExpression(pattern: pattern, options: [])
let matches = regex?.matches(in: sourceString, options: [],
                         range: NSRange(location: 0, length: sourceString.utf16.count))
let results = matches?.map({ (match) -> (Int, String) in // Array of type (Int: String) which
                                                         // represents index of expression and
                                                         // string capture
    let index = (1...match.numberOfRanges-1) // Go through all ranges to test which one was used
                 .map{ Range(match.range(at: $0), in: sourceString) != nil ? $0 : nil }
                 .compactMap { $0 }.first! // Previous map return array with nils and just one Int
                                           // with the correct position, lets apply compactMap to
                                           // get just this number

    let foundString = String(sourceString[Range(match.range(at: 0), in: sourceString)!])
    let position = match.range(at: 0).location
    let niceReponse = "\(foundString) [position: \(position)]"
    return (index - 1, niceReponse) // Let's substract 1 to index in order to match  zero based array index
})

print("Matches: \(results?.count ?? 0)\n")
results?.forEach({ result in
    print("Group \(result.0): \(result.1)")
})

Если вы запустите его, результат будет:

How many matches: 3

Expression 2: Swift [position: 0]
Expression 0: language [position: 17]
Expression 1: Objective-C [position: 55]

Надеюсь, я правильно понял ваш вопрос, и этот код поможет вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...