2017-02-27 101 views
2

我有一個字符串"323 ECO Economics Course 451 ENG English Course 789 Mathematical Topography"我想分裂使用正則表達式表達[0-9][0-9][0-9][A-Z][A-Z][A-Z]這個字符串,該函數返回數組:如何分割字符串使用正則表達式表達式

Array = 
["323 ECO Economics Course ", "451 ENG English Course", "789 Mathematical Topography"] 

我怎麼會去這樣做使用SWIFT ?

編輯 我的問題與鏈接到的不同。我意識到你可以使用myString.components(separatedBy: "splitting string")快速分割一個字符串問題是這個問題沒有解決如何使splitting string成爲一個正則表達式。我嘗試使用mystring.components(separatedBy: "[0-9][0-9][0-9][A-Z][A-Z][A-Z]", options: .regularExpression),但沒有奏效。

我怎樣才能讓separatedBy:部分的正則表達式?

+0

的可能的複製[如何分割在斯威夫特的字符串(http://stackoverflow.com/questions/25818197/how-to-split-a- string-in-swift) –

+0

也許你正在看着這個錯誤。爲什麼不簡單地使用'NSRegularExpression'類和它的'matches'函數來獲得你的正則表達式的所有匹配,而不是試圖找到一種使用正則表達式來「分割」字符串的奇特方式。 – rmaddy

+0

但是,在閱讀完您的問題之後,我認爲您可能會覺得這很有用。這是一個用Swift編寫的Regex類,可以放到你的項目中。我已經很容易和成功地將它用於多個項目。 https://gist.github.com/ningsuhen/dc6e589be7f5a41e7794/ – Kyle

回答

2

斯威夫特沒有本地正則表達式。但是Foundation提供了NSRegularExpression

import Foundation 

let toSearch = "323 ECO Economics Course 451 ENG English Course 789 MAT Mathematical Topography" 

let pattern = "[0-9]{3} [A-Z]{3}" 
let regex = try! NSRegularExpression(pattern: pattern, options: []) 

// NSRegularExpression works with objective-c NSString, which are utf16 encoded 
let matches = regex.matches(in: toSearch, range: NSMakeRange(0, toSearch.utf16.count)) 

// the combination of zip, dropFirst and map to optional here is a trick 
// to be able to map on [(result1, result2), (result2, result3), (result3, nil)] 
let results = zip(matches, matches.dropFirst().map { Optional.some($0) } + [nil]).map { current, next -> String in 
    let range = current.rangeAt(0) 
    let start = String.UTF16Index(range.location) 
    // if there's a next, use it's starting location as the ending of our match 
    // otherwise, go to the end of the searched string 
    let end = next.map { $0.rangeAt(0) }.map { String.UTF16Index($0.location) } ?? String.UTF16Index(toSearch.utf16.count) 

    return String(toSearch.utf16[start..<end])! 
} 

dump(results) 

運行,將輸出

▿ 3 elements 
    - "323 ECO Economics Course " 
    - "451 ENG English Course " 
    - "789 MAT Mathematical Topography" 
+0

非常有幫助。謝謝! – xxmbabanexx

3

您可以使用正則表達式"\\b[0-9]{1,}[a-zA-Z ]{1,}"這擴展從這個answer使用文字,CASEINSENSITIVE或正則表達式搜索字符串的所有範圍來獲得:

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 
    } 
} 

let inputString = "323 ECO Economics Course 451 ENG English Course 789 Mathematical Topography" 

let courses = inputString.ranges(of: "\\b[0-9]{1,}[a-zA-Z ]{1,}", options: .regularExpression).map{inputString[$0] } 

print(courses) // ["323 ECO Economics Course ", "451 ENG English Course ", "789 Mathematical Topography"] 
+0

如果你的課程代碼總是有3位數字,並且你的字符串至少有3個字符,你可以使用正則表達式'「\\ b [0-9] {3} [ a-zA-Z] {3,}「' –

+1

這是一個不錯的清潔解決方案。我喜歡如何構建一個範圍數組,然後使用map從原始字符串中提取子字符串。非常高雅的使用函數式編程。 (投票) –

+0

順便說一句,我看你也只是越過了門檻64k的聲譽。你是否像我那樣失望,在2^16沒有獲得新的獎賞? –