読者です 読者をやめる 読者になる 読者になる

エンジニアリングにはほど遠い

iPhoneアプリとかサイトとかをつくっていくブログです。

Swift2の正規表現マッチの簡易メソッド

Swift正規表現処理はObjective-C同様にとても面倒なので、色々な方が使いやすいように改良していますが、 自分もやってみました。(正規表現のパターンが不正な時はクラッシュします)

extension String {
    private func checkingResults(pattern:String) -> [NSTextCheckingResult] {
        return try! NSRegularExpression(pattern:pattern,options:NSRegularExpressionOptions())
        .matchesInString(self,
            options: NSMatchingOptions(),
            range: NSMakeRange(0, self.characters.count))
    }

    private func convertToStrings(result: NSTextCheckingResult) -> [String] {
        return Array(0..<result.numberOfRanges).map { index in
            (self as NSString).substringWithRange(result.rangeAtIndex(index))
        }
    }

    func match(pattern: String) -> [String]? {
        if let result = checkingResults(pattern).first {
            return convertToStrings(result)
        } else {
            return nil
        }
    }

    func matches(pattern: String) -> [[String]] {
        return checkingResults(pattern).map { result in convertToStrings(result) }
    }
}

matchのところとか、ぱっと見冗長に見えますね〜。こういうもんなんでしょうか。

結果

print("http://example.com".match("https?://(.*)"))
// Optional(["http://example.com", "example.com"]) 最初は全体、それ以降は各グループ
    
print("https://example.com".match("https?://(.*)"))
// Optional(["https://example.com", "example.com"])
    
print("a ab abc abcd".match("(.*?)\\s"))
// Optional(["a ", "a"]) 
    
print("a ab abc abcd".matches("(.*?)\\s"))
// [["a ", "a"], ["ab ", "ab"], ["abc ", "abc"]]

なんでこれが欲しかったのかというと、前回作った辞書機能の結果から品詞部分を抜き出したかったため。 definitionから以下の文字列が得られるので正規表現で抜き出す方針。
English |ˈɪŋglɪʃ| ▶adjective relating to England or its people or language. ▶noun 1 [ mass noun ] the language of England, now widely used in many varieties throughout the world. 2 (as plural noun the English) the people of England. 3 ...

func definition(word: String) -> String? {
    if let definition = DCSCopyTextDefinition(nil, word, CFRangeMake(0, word.characters.count))?
    .takeUnretainedValue() {
        return String(definition)
    } else {
        return nil
    }
}

if let definition = definition("English") {
    print(definition.matches("▶(.*?)\\s").map{ $0.last! })
    // ["adjective", "noun"]
}

これで、単語の品詞を得ることができました。