2015-09-08 146 views
4

我想在Apple使用多個分隔符或分隔符來分隔(或分解)Swift(1.2)中的字符串。使用多個分隔符在swift中分割字符串

我的字符串如下所示:

KEY1=subKey1=value&subkey2=valueKEY2=subkey1=value&subkey2=valueKEY3=subKey1=value&subkey3=value 

我已經格式化它爲方便閱讀:

KEY1=subKey1=value&subkey2=value 
KEY2=subkey1=value&subkey2=value 
KEY3=subKey1=value&subkey3=value 

大寫的 「鑰匙」 是預定義的名字。
我試圖這樣用做:

var splittedString = string.componentsSeparatedByString("KEY1") 

但你可以看到,我只能這麼做只有一個鍵作爲分隔符,所以我期待這樣的事情:

var splittedString = string.componentsSeperatedByStrings(["KEY1", "KEY2", "KEY3"]) 

所以結果會是:

[ 
    "KEY1" => "subKey1=value&subkey2=value", 
    "KEY2" => "subkey1=value&subkey2=value", 
    "KEY3" => "subkey1=value&subkey2=value" 
] 

是否有什麼內置到Swift 1.2中,我可以使用? 或者是否有某種擴展/庫可以輕鬆做到這一點?

感謝您的時間,祝您有美好的一天!

+0

不能老是value','KEYN'和'subKeyN'在它們的參數中有'&'或'='?或者'KEYN'也可以在'subKeyN'中(作爲子字符串?) – Larme

+0

您是否可以控制此字符串的生成方式?你怎麼知道價值何時結束,鑰匙何時開始?你可以添加另一個分隔符? –

回答

2

這是不是很有效,但它應該做的工作:

import Foundation 

extension String { 
    func componentsSeperatedByStrings(ss: [String]) -> [String] { 
    let inds = ss.flatMap { s in 
     self.rangeOfString(s).map { r in [r.startIndex, r.endIndex] } ?? [] 
    } 
    let ended = [startIndex] + inds + [endIndex] 
    let chunks = stride(from: 0, to: ended.count, by: 2) 
    let bounds = map(chunks) { i in (ended[i], ended[i+1]) } 
    return bounds 
     .map { (s, e) in self[s..<e] } 
     .filter { sl in !sl.isEmpty } 
    } 
} 



"KEY1=subKey1=value&subkey2=valueKEY2=subkey1=value&subkey2=valueKEY3=subKey1=value&subkey3=value".componentsSeperatedByStrings(["KEY1", "KEY2", "KEY3"]) 

// ["=subKey1=value&subkey2=value", "=subkey1=value&subkey2=value", "=subKey1=value&subkey3=value"] 

或者,如果你在字典的形式希望它:

import Foundation 

extension String { 
    func componentsSeperatedByStrings(ss: [String]) -> [String:String] { 
    let maybeRanges = ss.map { s in self.rangeOfString(s) } 
    let inds = maybeRanges.flatMap { $0.map { r in [r.startIndex, r.endIndex] } ?? [] } 
    let ended = [startIndex] + inds + [endIndex] 
    let chunks = stride(from: 0, to: ended.count, by: 2) 
    let bounds = map(chunks) { i in (ended[i], ended[i+1]) } 
    let values = bounds 
     .map { (s, e) in self[s..<e] } 
     .filter { sl in !sl.isEmpty } 
    let keys = filter(zip(maybeRanges, ss)) { (r, _) in r != nil } 
    var result: [String:String] = [:] 
    for ((_, k), v) in zip(keys, values) { result[k] = v } 
    return result 
    } 
} 


"KEY1=subKey1=value&subkey2=valueKEY2=subkey1=value&subkey2=valueKEY3=subKey1=value&subkey3=value".componentsSeperatedByStrings(["KEY1", "KEY2", "KEY3"]) 

// ["KEY3": "=subKey1=value&subkey3=value", "KEY2": "=subkey1=value&subkey2=value", "KEY1": "=subKey1=value&subkey2=value"] 

對於Swift 2:

import Foundation 

extension String { 
    func componentsSeperatedByStrings(ss: [String]) -> [String] { 
    let unshifted = ss 
     .flatMap { s in rangeOfString(s) } 
     .flatMap { r in [r.startIndex, r.endIndex] } 
    let inds = [startIndex] + unshifted + [endIndex] 
    return inds.startIndex 
     .stride(to: inds.endIndex, by: 2) 
     .map { i in (inds[i], inds[i+1]) } 
     .flatMap { (s, e) in s == e ? nil : self[s..<e] } 
    } 
} 
+0

謝謝你!工作很好,直到我更新到新的xcode 7GM和swift 2.0語法,你有什麼想法我可以改變代碼,所以它會工作? 「stride()」函數給我一個錯誤: let chunks = stride(from:0,to:ended.count,by:2) 「Stride(from:to:by)is unavailable」 Thanks in在那裏預先 – Rick

+1

更新。 – oisdk

+0

非常感謝!奇蹟般有效 :) – Rick

0

你可以用正則表達式來做到這一點。下面的代碼片段有點笨拙,並且不是真正的失效保護,但它應該給你一個想法。

let string = "KEY1=subKey1=value&subkey2=valueKEY2=subkey1=value&subkey2=valueKEY3=subKey1=value&subkey3=value" 
let re = NSRegularExpression(pattern: "(KEY1|KEY2|KEY3)=", options: nil, error: nil)! 
let matches = re.matchesInString(string, options: nil, 
    range: NSMakeRange(0, count(string))) 

var dict = [String: String]() 

for (index, match) in enumerate(matches) { 
    let key = (string as NSString).substringWithRange(
     NSMakeRange(match.range.location, match.range.length - 1)) 

    let valueStart = match.range.location + match.range.length 
    let valueEnd = index < matches.count - 1 ? matches[index + 1].range.location 
              : count(string) 
    let value = (string as NSString).substringWithRange(
     NSMakeRange(valueStart, valueEnd - valueStart)) 

    dict[key] = value 
} 

dict最終值是

[KEY3: subKey1=value&subkey3=value, 
KEY2: subkey1=value&subkey2=value, 
KEY1: subKey1=value&subkey2=value] 
+0

感謝您的回答,我看到它的工作原理。 但是實際使用的字符串沒有格式化爲「KEYX」的鍵,其中X是Int。 我擁有完全不同的密鑰,更像「NS」,「AAAA」和「MX」。 我如何在代碼中使用這些鍵實現一個數組? 非常感謝您的時間! – Rick

+0

@Rick對不起,爲了記錄,我更新了我的答案以支持任意鍵名。這個想法是使用一個或者或者像表達式'(KEY1 | KEY2 | KEY3)'。 – hennes

+0

謝謝你,我正在使用oisdk的字符串擴展方法,這很好用,但我會試一試你的方法,看看最好的方法。 – Rick

0

夫特2用於前向兼容性

使用正則表達式:

let string = "KEY1=subKey1=value&subkey2=valueKEY2=subkey1=value&subkey2=valueKEY3=subKey1=value&subkey3=value" 
let nsString :NSString = string 
let stringRange = NSMakeRange(0, string.utf16.count) 
let pattern = "(KEY\\d)=([^=]+=[^&]+[^=]+?=[^K]+)" 
var results = [String:String]() 
do { 
    var regEx = try NSRegularExpression(pattern:pattern, options:[]) 
    regEx.enumerateMatchesInString(string, options: [], range: stringRange) { 
     (result : NSTextCheckingResult?, _, _) in 
     if let result = result { 
      if result.numberOfRanges == 3 { 
       let key = nsString.substringWithRange(result.rangeAtIndex(1)) 
       let value = nsString.substringWithRange(result.rangeAtIndex(2)) 
       results[key] = value 
      } 
     } 
    } 
} 
catch { 
    print("Bad Pattern") 
} 

結果:["KEY3": "subKey1=value&subkey3=value", "KEY2": "subkey1=value&subkey2=value", "KEY1": "subKey1=value&subkey2=value"]

4

人們也可以使用下面的方法來拆分在多個分隔符的字符串外殼鑰匙是單個字符:

let stringData = "K01L02M03" 
let res = stringData.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "KLM")); 

res將包含["01", "02", "03"]

如果有人知道任何一種特殊語法的方法擴展到每個鍵多個字符歡迎您的建議和改善這個答案