2015-05-19 45 views
0

我需要找出一種方法來將某些字符序列中的字符串拆分爲一個字符串數組,但是我當前實現的問題是,如果在字符串中出現兩個或更多個拆分,它將覆蓋前一個。在幾個索引處分割一個字符串 - > [String]?

考慮在stck分割以下字符串...

stockwell 

用正則表達式匹配,我得到的兩場比賽在範圍內,但如果我嘗試在一個循環之後組裝這些到一個數組,第二場比賽覆蓋第一...

stockwell: (0,2) --> st --> _st_ockwell 
stockwell: (3,2) --> ck --> sto_ck_well 

將是最佳的這是什麼,可以在幾個指數將一個字符串分解成[String]一個字符串擴展方法,但我還沒有成功還沒有想出一個。

有人可以給我一些幫助嗎?

+1

您對分隔字符串的順序有任何保證嗎?他們可能會匹配多次或每次只匹配一次?你能保證他們不會有任何重疊嗎?如「st」和「tr」,它們都可以是「強度」一詞中兩個不同匹配的一部分。你目前的實施是什麼? – ColGraff

+0

沒有保證,因爲訂單或分隔部分在一個字符串中出現的頻率。關於重疊,我可以將這樣的字符串(如「str」)添加到排除列表中,以便它與之匹配。事實上,似乎我的正則表達式已經注意到沒有這樣的重疊。問題是如何組裝一個適當的段數組。我目前的實現依賴於來自ExSwift和我自己的util擴展的相當多的外部代碼。我會看看我是否可以把簡單的例子放在一起。 – BadmintonCat

+0

如果是我,我只需使用'componentsSeperatedByString:'爲我的每個令牌創建一個樹狀結構,然後簡單地將其平坦化。這可能不是最佳的,但它會起作用。 – nhgrif

回答

1

如何:

extension String { 

    func multiSplit(inds: [String.Index]) -> [String] { 

    if let loc = inds.last { 

     return self[self.startIndex..<loc].multiSplit(Array(dropLast(inds))) + [self[loc..<self.endIndex]] 

    } else { 

     return [self] 

    } 
    } 
} 

let string = "abcdef" 

let inds = [ 
    string.startIndex.successor().successor(), 
    string.endIndex.predecessor().predecessor() 
] 

string.multiSplit(inds) // ["ab", "cd", "ef"] 

的指數你給它必須是爲了工作。

這是一個遞歸函數 - 它接受指定數組中的最後一個索引(inds),並將該字符串拆分爲該索引。該分割的前半部分被遞歸地賦予其自身,並刪除索引數組的最後一個元素。如果索引數組爲空,那麼「if let」會失敗,所以它只是返回沒有任何拆分的字符串,而是以一個數組的形式返回。

在這個例子中,它將首先在它給出的最後一個索引處進行拆分,並得到兩個字符串:「abcd」和「ef」。然後,函數使用「abcd」和一個沒有最後一個元素(dropLast())的索引數組來調用它自己。在這個功能中,它會將「abcd」分成「ab」和「cd」,並在「ab」上再次調用自己。但是,由於它將空數組傳遞給該函數,因此inds.last將失敗,並且不會分割任何內容,只返回[「ab」](帶有return [self]的行)。這取決於上面的功能 - 它將分割(「cd」)附加到它上面,並返回[「ab」,「cd」]。最後,這個函數返回到上面的函數,它附加了它的分割,並且它返回了答案:[「ab,」cd「,」ef「]。

這一切都正常Swift雖然沒有任何進口或任何東西。

如果用指數處理亂序,你可以對它們進行排序:

let string = "abcdef" 

let inds = [ 
    string.endIndex.predecessor().predecessor(), 
    string.startIndex.successor().successor() 
] 

string.multiSplit(sorted(inds)) // ["ab", "cd", "ef"] 

另外,如果你想從函數中刪除空字符串:

extension String { 

    func multiSplit(inds: [String.Index]) -> [String] { 

    if let loc = inds.last { 

    return (
     self[self.startIndex..<loc] 
     .multiSplit(Array(dropLast(inds))) 
     + [self[loc..<self.endIndex]] 
    ).filter{!$0.isEmpty} 

    } else { 

     return [self] 

    } 
    } 
} 
+0

last()和dropLast()是做什麼的?這是你自己的代碼?你能包括它嗎? – BadmintonCat

+0

否 - last()返回一個可選項 - 如果數組不爲空,則返回數組中的最後一個元素;如果是,則返回nil。我會稍微修改一下這個答案,使其更加清晰。 – oisdk

+1

[字符串沒有整數索引](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-ID494 )他們有自己的指數。如果你想從一個整數得到一個String.Index,你必須使用advance(someString.startIndex,intIndex) – oisdk

1

您可以使用前瞻和回顧後匹配的位置:

(?=st)|(?<=st)|(?=ck)|(?<=ck) 

而且隨着_

更換見DEMO

+0

好吧,這是相當有用的,但我不知道它是如何幫助我的原始問題,如何正確組裝匹配/範圍從正則表達式到字符串數組。如果Swift的String類的NSRegularExpression有一些API可以通過regexp(像其他一些語言)一樣拆分爲一個數組,但是看起來沒有那樣。 – BadmintonCat

1

另一個辦法這取決於確保你的分隔符不重疊或包含對方。

import Foundation 

let initial = "stockwell" 
let firstSeparator = "st" 
let secondSeparator = "ck" 
var separated = [String]() 
let firstSplit = initial.componentsSeparatedByString(firstSeparator) 
for next in [firstSeparator].join(firstSplit.map{[$0]}) { 
    let secondSplit = next.componentsSeparatedByString(secondSeparator) 
    separated += [secondSeparator].join(secondSplit.map{[$0]}) 
} 
separated // => ["", "st", "o", "ck", "well"] 

它通過使用第一分隔符串組分離到一個數組,插入分隔符劃分爲元件之間的陣列,然後做同樣的每個元素與下一個定界符的新的數組英寸