我还没有弄清楚如何在Swift中获得字符串的子字符串:
var str = “Hello, playground”
func test(str: String) -> String {
return str.substringWithRange( /* What goes here? */ )
}
test (str)
我不能在Swift中创建一个范围。自动完成在游乐场不是超级有用的-这是它的建议:
return str.substringWithRange(aRange: Range<String.Index>)
我在Swift标准参考库中没有找到任何有用的东西。下面是另一个大胆的猜测:
return str.substringWithRange(Range(0, 1))
这:
let r:Range<String.Index> = Range<String.Index>(start: 0, end: 2)
return str.substringWithRange(r)
我看到了其他答案(在Swift字符串中查找字符索引),似乎表明,由于字符串是NSString的桥类型,“旧”方法应该工作,但不清楚如何-例如,这也不工作(似乎不是有效的语法):
let x = str.substringWithRange(NSMakeRange(0, 3))
想法吗?
关于如何解决这个问题,已经有很多很好的例子。最初的问题是关于使用substringWithRange,但正如已经指出的那样,这比仅仅做自己的扩展更难。
上述范围的解决方案是很好的。你还可以用其他十几种方法来做到这一点。下面是另一个例子,告诉你如何做到这一点:
extension String{
func sub(start: Int, length: Int) -> String {
assert(start >= 0, "Cannot extract from a negative starting index")
assert(length >= 0, "Cannot extract a negative length string")
assert(start <= countElements(self) - 1, "cannot start beyond the end")
assert(start + length <= countElements(self), "substring goes past the end of the original")
var a = self.substringFromIndex(start)
var b = a.substringToIndex(length)
return b
}
}
var s = "apple12345"
println(s.sub(6, length: 4))
// prints "2345"
在我写这篇文章的时候,没有一个扩展是完全兼容Swift 4.2的,所以这里有一个涵盖了我能想到的所有需求:
extension String {
func substring(from: Int?, to: Int?) -> String {
if let start = from {
guard start < self.count else {
return ""
}
}
if let end = to {
guard end >= 0 else {
return ""
}
}
if let start = from, let end = to {
guard end - start >= 0 else {
return ""
}
}
let startIndex: String.Index
if let start = from, start >= 0 {
startIndex = self.index(self.startIndex, offsetBy: start)
} else {
startIndex = self.startIndex
}
let endIndex: String.Index
if let end = to, end >= 0, end < self.count {
endIndex = self.index(self.startIndex, offsetBy: end + 1)
} else {
endIndex = self.endIndex
}
return String(self[startIndex ..< endIndex])
}
func substring(from: Int) -> String {
return self.substring(from: from, to: nil)
}
func substring(to: Int) -> String {
return self.substring(from: nil, to: to)
}
func substring(from: Int?, length: Int) -> String {
guard length > 0 else {
return ""
}
let end: Int
if let start = from, start > 0 {
end = start + length - 1
} else {
end = length - 1
}
return self.substring(from: from, to: end)
}
func substring(length: Int, to: Int?) -> String {
guard let end = to, end > 0, length > 0 else {
return ""
}
let start: Int
if let end = to, end - length > 0 {
start = end - length + 1
} else {
start = 0
}
return self.substring(from: start, to: to)
}
}
然后,你可以使用:
let string = "Hello,World!"
字符串。substring(from: 1, to: 7)得到你:ello,Wo
字符串。substring(to: 7)得到你:Hello,Wo
字符串。substring(from: 3)得到你:lo,World!
字符串。子字符串(从:1,长度:4)得到你:ello
字符串。substring(长度:4,到:7)得到你:o,Wo
更新的子字符串(from: Int?, length: Int)支持从零开始。
一旦找到正确的语法,它比这里的任何答案都要简单得多。
我想把[和]
let myString = "[ABCDEFGHI]"
let startIndex = advance(myString.startIndex, 1) //advance as much as you like
let endIndex = advance(myString.endIndex, -1)
let range = startIndex..<endIndex
let myNewString = myString.substringWithRange( range )
结果是"ABCDEFGHI"
startIndex和endIndex也可以用在
let mySubString = myString.substringFromIndex(startIndex)
等等!
PS:正如注释中所指出的,在xcode 7和iOS9附带的swift 2中有一些语法变化!
请看这一页
注意:@airspeedswift对这种方法的权衡提出了一些非常深刻的观点,特别是隐藏的性能影响。字符串不是简单的野兽,获得特定的索引可能需要O(n)时间,这意味着使用下标的循环可能是O(n²)。我警告过你了。
你只需要添加一个新的下标函数,它接受一个范围,并使用advancedBy()走到你想要的地方:
import Foundation
extension String {
subscript (r: Range<Int>) -> String {
get {
let startIndex = self.startIndex.advancedBy(r.startIndex)
let endIndex = startIndex.advancedBy(r.endIndex - r.startIndex)
return self[Range(start: startIndex, end: endIndex)]
}
}
}
var s = "Hello, playground"
println(s[0...5]) // ==> "Hello,"
println(s[0..<5]) // ==> "Hello"
(这绝对应该是语言的一部分。请dupe rdar://17158813)
为了好玩,你还可以在索引上添加一个+运算符:
func +<T: ForwardIndex>(var index: T, var count: Int) -> T {
for (; count > 0; --count) {
index = index.succ()
}
return index
}
s.substringWithRange(s.startIndex+2 .. s.startIndex+5)
(我还不知道这个是否应该成为语言的一部分。)