我怎样才能得到字符串的第n个字符?我尝试了括号([])访问器,没有运气。
var string = "Hello, world!"
var firstChar = string[0] // Throws error
错误:'下标'是不可用的:不能下标String与Int,请参阅文档注释讨论
我怎样才能得到字符串的第n个字符?我尝试了括号([])访问器,没有运气。
var string = "Hello, world!"
var firstChar = string[0] // Throws error
错误:'下标'是不可用的:不能下标String与Int,请参阅文档注释讨论
当前回答
为了提供主题并显示快速下标的可能性,这里有一个基于“substring-toolbox”下标的小字符串
这些方法是安全的,并且不会遍历字符串索引
extension String {
// string[i] -> one string char
subscript(pos: Int) -> String { return String(Array(self)[min(self.length-1,max(0,pos))]) }
// string[pos,len] -> substring from pos for len chars on the left
subscript(pos: Int, len: Int) -> String { return self[pos, len, .pos_len, .left2right] }
// string[pos, len, .right2left] -> substring from pos for len chars on the right
subscript(pos: Int, len: Int, way: Way) -> String { return self[pos, len, .pos_len, way] }
// string[range] -> substring form start pos on the left to end pos on the right
subscript(range: Range<Int>) -> String { return self[range.startIndex, range.endIndex, .start_end, .left2right] }
// string[range, .right2left] -> substring start pos on the right to end pos on the left
subscript(range: Range<Int>, way: Way) -> String { return self[range.startIndex, range.endIndex, .start_end, way] }
var length: Int { return countElements(self) }
enum Mode { case pos_len, start_end }
enum Way { case left2right, right2left }
subscript(var val1: Int, var val2: Int, mode: Mode, way: Way) -> String {
if mode == .start_end {
if val1 > val2 { let val=val1 ; val1=val2 ; val2=val }
val2 = val2-val1
}
if way == .left2right {
val1 = min(self.length-1, max(0,val1))
val2 = min(self.length-val1, max(1,val2))
} else {
let val1_ = val1
val1 = min(self.length-1, max(0, self.length-val1_-val2 ))
val2 = max(1, (self.length-1-val1_)-(val1-1) )
}
return self.bridgeToObjectiveC().substringWithRange(NSMakeRange(val1, val2))
//-- Alternative code without bridge --
//var range: Range<Int> = pos...(pos+len-1)
//var start = advance(startIndex, range.startIndex)
//var end = advance(startIndex, range.endIndex)
//return self.substringWithRange(Range(start: start, end: end))
}
}
println("0123456789"[3]) // return "3"
println("0123456789"[3,2]) // return "34"
println("0123456789"[3,2,.right2left]) // return "56"
println("0123456789"[5,10,.pos_len,.left2right]) // return "56789"
println("0123456789"[8,120,.pos_len,.right2left]) // return "01"
println("0123456789"[120,120,.pos_len,.left2right]) // return "9"
println("0123456789"[0...4]) // return "01234"
println("0123456789"[0..4]) // return "0123"
println("0123456789"[0...4,.right2left]) // return "56789"
println("0123456789"[4...0,.right2left]) // return "678" << because ??? range can wear endIndex at 0 ???
其他回答
允许负指数
它总是有用的,不必总是写string[string]。长度- 1]用于在使用下标扩展名时获取最后一个字符。这(Swift 3)扩展允许负索引,范围和CountableClosedRange。
extension String {
var count: Int { return self.characters.count }
subscript (i: Int) -> Character {
// wraps out of bounds indices
let j = i % self.count
// wraps negative indices
let x = j < 0 ? j + self.count : j
// quick exit for first
guard x != 0 else {
return self.characters.first!
}
// quick exit for last
guard x != count - 1 else {
return self.characters.last!
}
return self[self.index(self.startIndex, offsetBy: x)]
}
subscript (r: Range<Int>) -> String {
let lb = r.lowerBound
let ub = r.upperBound
// quick exit for one character
guard lb != ub else { return String(self[lb]) }
return self[self.index(self.startIndex, offsetBy: lb)..<self.index(self.startIndex, offsetBy: ub)]
}
subscript (r: CountableClosedRange<Int>) -> String {
return self[r.lowerBound..<r.upperBound + 1]
}
}
如何使用:
var text = "Hello World"
text[-1] // d
text[2] // l
text[12] // e
text[0...4] // Hello
text[0..<4] // Hell
对于更彻底的程序员:在这个扩展中包括一个防止空字符串的保护
subscript (i: Int) -> Character {
guard self.count != 0 else { return '' }
...
}
subscript (r: Range<Int>) -> String {
guard self.count != 0 else { return "" }
...
}
我想指出的是,如果你有一个很大的字符串,并且需要从中随机访问许多字符,你可能想要支付额外的内存成本,并将字符串转换为一个数组以获得更好的性能:
// Pay up front for O(N) memory
let chars = Array(veryLargeString.characters)
for i in 0...veryLargeNumber {
// Benefit from O(1) access
print(chars[i])
}
对我来说最有效的方法是:
var firstName = "Olivia"
var lastName = "Pope"
var nameInitials.text = "\(firstName.prefix(1))" + "\ (lastName.prefix(1))"
输出:“OP”
一个类似蟒蛇的解决方案,允许你使用负下标,
var str = "Hello world!"
str[-1] // "!"
可能是:
extension String {
subscript (var index:Int)->Character{
get {
let n = distance(self.startIndex, self.endIndex)
index %= n
if index < 0 { index += n }
return self[advance(startIndex, index)]
}
}
}
顺便说一下,调换整个python的切片符号可能是值得的
为了提供主题并显示快速下标的可能性,这里有一个基于“substring-toolbox”下标的小字符串
这些方法是安全的,并且不会遍历字符串索引
extension String {
// string[i] -> one string char
subscript(pos: Int) -> String { return String(Array(self)[min(self.length-1,max(0,pos))]) }
// string[pos,len] -> substring from pos for len chars on the left
subscript(pos: Int, len: Int) -> String { return self[pos, len, .pos_len, .left2right] }
// string[pos, len, .right2left] -> substring from pos for len chars on the right
subscript(pos: Int, len: Int, way: Way) -> String { return self[pos, len, .pos_len, way] }
// string[range] -> substring form start pos on the left to end pos on the right
subscript(range: Range<Int>) -> String { return self[range.startIndex, range.endIndex, .start_end, .left2right] }
// string[range, .right2left] -> substring start pos on the right to end pos on the left
subscript(range: Range<Int>, way: Way) -> String { return self[range.startIndex, range.endIndex, .start_end, way] }
var length: Int { return countElements(self) }
enum Mode { case pos_len, start_end }
enum Way { case left2right, right2left }
subscript(var val1: Int, var val2: Int, mode: Mode, way: Way) -> String {
if mode == .start_end {
if val1 > val2 { let val=val1 ; val1=val2 ; val2=val }
val2 = val2-val1
}
if way == .left2right {
val1 = min(self.length-1, max(0,val1))
val2 = min(self.length-val1, max(1,val2))
} else {
let val1_ = val1
val1 = min(self.length-1, max(0, self.length-val1_-val2 ))
val2 = max(1, (self.length-1-val1_)-(val1-1) )
}
return self.bridgeToObjectiveC().substringWithRange(NSMakeRange(val1, val2))
//-- Alternative code without bridge --
//var range: Range<Int> = pos...(pos+len-1)
//var start = advance(startIndex, range.startIndex)
//var end = advance(startIndex, range.endIndex)
//return self.substringWithRange(Range(start: start, end: end))
}
}
println("0123456789"[3]) // return "3"
println("0123456789"[3,2]) // return "34"
println("0123456789"[3,2,.right2left]) // return "56"
println("0123456789"[5,10,.pos_len,.left2right]) // return "56789"
println("0123456789"[8,120,.pos_len,.right2left]) // return "01"
println("0123456789"[120,120,.pos_len,.left2right]) // return "9"
println("0123456789"[0...4]) // return "01234"
println("0123456789"[0..4]) // return "0123"
println("0123456789"[0...4,.right2left]) // return "56789"
println("0123456789"[4...0,.right2left]) // return "678" << because ??? range can wear endIndex at 0 ???