假设我有字符串"a:b:c"
我该如何拆分它以便最终得到数组["a", ":", "b", ":", "c"]
?
我的最终目标是我可以在正则表达式中传递我想要的任何分隔符(不仅仅是":")但是我无法弄清楚如何在没有Swift 2的情况下拆分字符串失去它分裂的角色。
[编辑]澄清(基于评论)我不是试图按字符分割它,而且我不想分开":"特别。它只是一个随机分隔符,我认为这将提供一个简单的例子。我想知道如何在正则表达式中定义的任何随机分隔符上拆分字符串,而不是松散分隔符。 " fooBerry-BazClom *"如[B\\-*]
这样的内容分开会让我["foo", "B", "erry", "-", "B", "az", "Clom", "*"]
答案 0 :(得分:1)
我相信这会解决问题(不确定它是否非常有效):
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
使用如下:
extension String
{
func componentsStartingFromCharactersInSet(searchSet: NSCharacterSet) -> [String]
{
if self == "" { return [] }
if let firstDelimiter = rangeOfCharacterFromSet(searchSet)
{
let delimiter = self.substringWithRange(firstDelimiter)
var result:[String] = []
if let rightIndex = firstDelimiter.last?.successor()
{ result = self.substringFromIndex(rightIndex).componentsStartingFromCharactersInSet(searchSet) }
result.insert(delimiter, atIndex:0)
if !hasPrefix(delimiter)
{ result.insert(self.substringToIndex(firstDelimiter.first!), atIndex:0) }
return result
}
return [self]
}
}
返回[&#34; foo&#34;,&#34; B&#34;,&#34; erry&#34;,&#34; - &#34;,&#34; B&#34; ,&#34; azClom&#34;,&#34; *&#34;]
鉴于您需要一个正则表达式来表达分隔符,我不确定您的目标是什么,但这里是基于正则表达式的修改版本(以及一些摆弄范围类型转换):
let searchSet = NSCharacterSet(charactersInString:"B\\-*")
"fooBerry-BazClom*".componentsStartingFromCharactersInSet(searchSet)
我必须在正则表达式中使用不同的语法来定义分隔符。这就是为什么我不确定我完全明白你需要什么。
extension String
{
var length:Int {return (self as NSString).length }
func stringRange(range:NSRange) -> Range<String.Index>
{
let start = self.startIndex.advancedBy(range.location)
let end = start.advancedBy(range.length)
return Range<String.Index>(start: start, end: end)
}
func componentsFromRegExp(regExp:String) -> [String]
{
if self == "" { return [] }
do
{
let expression = try NSRegularExpression(pattern: regExp, options: NSRegularExpressionOptions.CaseInsensitive)
return self.componentsFromRegExp(expression)
}
catch { return [self] }
}
func componentsFromRegExp(regExp:NSRegularExpression) -> [String]
{
if self == "" { return [] }
if let firstMatch = regExp.firstMatchInString(self, options:NSMatchingOptions(rawValue:0), range:NSMakeRange(0, self.length) )
where firstMatch.range.length > 0
{
let firstDelimiter = self.stringRange(firstMatch.range)
let delimiter = self.substringWithRange(firstDelimiter)
var result:[String] = []
if let rightIndex = firstDelimiter.last?.successor()
{ result = self.substringFromIndex(rightIndex).componentsFromRegExp(regExp) }
result.insert(delimiter, atIndex:0)
if !hasPrefix(delimiter)
{ result.insert(self.substringToIndex(firstDelimiter.first!), atIndex:0) }
return result
}
return [self]
}
}
答案 1 :(得分:0)
您可以通过在模板中添加反向引用来解决此问题。对我来说这感觉有点粗糙,但是从提出的解决方案来看,它是最快的(见本文末尾的性能记录)
let y="YupNope-FractalOrangexbluey";
let testPattern="(Nope|-|[xy])";
func splitStingOnRegex(aString: String, aPattern: String) -> Array<String> {
do{
let regEx = try NSRegularExpression(pattern: aPattern, options: NSRegularExpressionOptions())
let template = "\u{16E5}\u{16E5}\u{16E5}$1\u{16E5}\u{16E5}\u{16E5}"
// u+1635 is an ancient rune unlikely to show up in modern text (or ancient (i hope)) 3 times in a row
let modifiedString = regEx.stringByReplacingMatchesInString(
aString, options: NSMatchingOptions(),
range: NSMakeRange(0, aString.characters.count),
withTemplate:template)
let cleanedSideBySideMatches = modifiedString.stringByReplacingOccurrencesOfString("\u{16E5}\u{16E5}\u{16E5}\u{16E5}\u{16E5}\u{16E5}", withString: "\u{16E5}\u{16E5}\u{16E5}", options: NSStringCompareOptions.LiteralSearch, range: nil)
let arrPlusOne = cleanedSideBySideMatches.componentsSeparatedByString("\u{16E5}\u{16E5}\u{16E5}")
if arrPlusOne.count > 1 {
return Array(arrPlusOne[0...(arrPlusOne.count - 2)]);
// because there's always an extra one at the end
} else {
return arrPlusOne;
// nothing was matched
}
} catch {
return []
}
}
splitStingOnRegex(y, aPattern: testPattern);
// ["Yup", "Nope", "-", "FractalOrange", "x", "blue", "y"]
或者,您可以获取匹配数组,以及不匹配的数组并将它们压缩在一起。
func newSplitStringOnRegex(aString: String, aPattern: String) -> Array<String>{
do {
let regEx = try NSRegularExpression(pattern: aPattern, options: NSRegularExpressionOptions())
let template = "\u{16E5}\u{16E5}\u{16E5}"
let aNSString = aString as NSString;
// u+1635 is an ancient rune unlikely to show up in modern text (or ancient (i hope)) 3 times in a row
var modifiedString = regEx.stringByReplacingMatchesInString(
aString, options: NSMatchingOptions(),
range: NSMakeRange(0, aString.characters.count),
withTemplate:template)
// if the first match was at the beginning
// we'll end up with an extra "" at the start of our array when we split
if modifiedString.hasPrefix(template) {
modifiedString = (modifiedString as NSString).substringFromIndex(3);
}
modifiedString
let unmatchedItems = modifiedString.componentsSeparatedByString(template)
unmatchedItems.last
let matchRanges = regEx.matchesInString(aString, options: NSMatchingOptions(), range: NSMakeRange(0, aString.characters.count));
let matches = matchRanges.map { aNSString.substringWithRange($0.range)}
// now let's zip the matched and unmatched items together
let merged = zip(unmatchedItems, matches).map{[$0.0, $0.1]}.flatMap({$0});
// zip will leave any extra items off the end
// because this is ultimately a split we'll never have more than one extra
if unmatchedItems.count > matches.count {
return merged + [unmatchedItems.last!];
} else if matches.count > unmatchedItems.count {
return merged + [matches.last!];
}
// no extras
return merged;
} catch {
return Array<String>();
}
}
newSplitStringOnRegex(text, aPattern: testPattern);
// ["Yup", "Nope", "", "Nope", "FractalOrange", "-", "blue", "x", "", "y"]
测试这两个,加上我的计算机上的Alain T,测试字符串有~50个匹配项和~50个分隔符:我每次运行1000次并得到这些结果:
所以你有它。赢得胜利的简单易懂的解决方案。 ;)