在Swift编程语言中获得一个string的第n个字符
我怎样才能得到一个string的第n个字符? 我尝试括号( []
)访问器没有运气。
var string = "Hello, world!" var firstChar = string[0] // Throws error
Swift 2 :
extension String { subscript (i: Int) -> Character { return self[self.startIndex.advancedBy(i)] } subscript (i: Int) -> String { return String(self[i] as Character) } subscript (r: Range<Int>) -> String { let start = startIndex.advancedBy(r.startIndex) let end = start.advancedBy(r.endIndex - r.startIndex) return self[Range(start ..< end)] } }
Swift 3:
extension String { subscript (i: Int) -> Character { return self[index(startIndex, offsetBy: i)] } subscript (i: Int) -> String { return String(self[i] as Character) } subscript (r: Range<Int>) -> String { let start = index(startIndex, offsetBy: r.lowerBound) let end = index(startIndex, offsetBy: r.upperBound) return self[Range(start ..< end)] } }
现在,这些都是平等的。
"abcde"[0] == "a" "abcde"[0...2] == "abc" "abcde"[2..<4] == "cd"
string支持下标(使用[] )开箱即用:
斯威夫特4
let str = "Hello, world!" let index = str.index(str.startIndex, offsetBy: 4) str[index] // returns Character 'o' let endIndex = str.index(str.endIndex, offsetBy:-2) str[index ..< endIndex] // returns String "o, worl" String(str.suffix(from: index)) // returns String "o, world!" String(str.prefix(upTo: index)) // returns String "Hell"
或者,你可以使用这个更简洁的语法:
let str = "abcdef" str[1 ..< 3] // returns "bc" str[5] // returns "f" str[80] // returns "" str.substring(fromIndex: 3) // returns "def" str.substring(toIndex: str.length - 2) // returns "abcd"
…但为此,你需要添加这个string扩展(完全testing):
extension String { var length: Int { return self.characters.count } subscript (i: Int) -> String { return self[i ..< i + 1] } func substring(fromIndex: Int) -> String { return self[min(fromIndex, length) ..< length] } func substring(toIndex: Int) -> String { return self[0 ..< max(0, toIndex)] } subscript (r: Range<Int>) -> String { let range = Range(uncheckedBounds: (lower: max(0, min(length, r.lowerBound)), upper: min(length, max(0, r.upperBound)))) let start = index(startIndex, offsetBy: range.lowerBound) let end = index(start, offsetBy: range.upperBound - range.lowerBound) return String(self[start ..< end]) } }
不使用整数索引,只使用String.Index
。 主要是线性复杂的。 您也可以从String.Index
创build范围,并使用它们来获取子string。
Swift 3.0
let firstChar = someString[someString.startIndex] let lastChar = someString[someString.index(before: someString.endIndex)] let charAtIndex = someString[someString.index(someString.startIndex, offsetBy: 10)] let range = someString.startIndex..<someString.index(someString.startIndex, offsetBy: 10) let substring = someString[range]
Swift 2.x
let firstChar = someString[someString.startIndex] let lastChar = someString[someString.endIndex.predecessor()] let charAtIndex = someString[someString.startIndex.advanceBy(10)] let range = someString.startIndex..<someString.startIndex.advanceBy(10) let subtring = someString[range]
请注意,您不能使用从一个string创build的索引(或范围)到另一个string
let index10 = someString.startIndex.advanceBy(10) //will compile //sometimes it will work but sometimes it will crash or result in undefined behaviour let charFromAnotherString = anotherString[index10]
我刚刚提出了这个整洁的解决方法
var firstChar = Array(string)[0]
Xcode 9•Swift 4
extension Character { var string: String { return String(self) } } extension String.CharacterView { var string: String { return String(self) } } extension Sequence where Iterator.Element == UnicodeScalar { var string: String { return String(String.UnicodeScalarView(self)) } }
extension String { func index(at offset: Int) -> Index? { precondition(offset >= 0, "offset can't be negative") return index(startIndex, offsetBy: offset, limitedBy: index(before: endIndex)) } func character(at offset: Int) -> Character? { precondition(offset >= 0, "offset can't be negative") guard let index = index(at: offset) else { return nil } return self[index] } subscript(offset: Int) -> String { precondition(offset >= 0, "offset can't be negative") guard let character = character(at: offset) else { return "" } return String(character) } subscript(range: Range<Int>) -> Substring { precondition(range.lowerBound >= 0, "range lowerBound can't be negative") guard let startIndex = index(at: range.lowerBound) else { return "" } return self[startIndex..<(index(startIndex, offsetBy: range.count, limitedBy: endIndex) ?? endIndex)] } subscript(range: ClosedRange<Int>) -> Substring { precondition(range.lowerBound >= 0, "range lowerBound can't be negative") guard let startIndex = index(at: range.lowerBound) else { return "" } return self[startIndex..<(index(startIndex, offsetBy: range.count, limitedBy: endIndex) ?? endIndex)] } subscript(partialRange: PartialRangeFrom<Int>) -> Substring { return self[partialRange.lowerBound..<endIndex.encodedOffset] } subscript(partialRange: PartialRangeUpTo<Int>) -> Substring { return self[startIndex.encodedOffset..<partialRange.upperBound] } subscript(partialRange: PartialRangeThrough<Int>) -> Substring { return self[startIndex.encodedOffset...partialRange.upperBound] } }
testing
let test = "Hello USA 🇺🇸!!! Hello Brazil 🇧🇷!!!" test.character(at: 10) // "🇺🇸" test.character(at: 11) // "!" test[10...] // "🇺🇸!!! Hello Brazil 🇧🇷!!!" test[...10] // "Hello USA 🇺🇸" test[..<10] // "Hello USA " test.first // "H" test.last // "!"
Xcode 8.3•Swift 3.1
extension String { subscript(pos: Int) -> String { precondition(pos >= 0, "character position can't be negative") return self[pos...pos] } subscript(range: Range<Int>) -> String { precondition(range.lowerBound >= 0, "range lowerBound can't be negative") let lowerIndex = index(startIndex, offsetBy: range.lowerBound, limitedBy: endIndex) ?? endIndex return self[lowerIndex..<(index(lowerIndex, offsetBy: range.count, limitedBy: endIndex) ?? endIndex)] } subscript(range: ClosedRange<Int>) -> String { precondition(range.lowerBound >= 0, "range lowerBound can't be negative") let lowerIndex = index(startIndex, offsetBy: range.lowerBound, limitedBy: endIndex) ?? endIndex return self[lowerIndex..<(index(lowerIndex, offsetBy: range.count, limitedBy: endIndex) ?? endIndex)] } }
斯威夫特4
let str = "My String"
索引处的string
let index = str.index(str.startIndex, offsetBy: 3) String(str[index]) // "S"
子
let startIndex = str.index(str.startIndex, offsetBy: 3) let endIndex = str.index(str.startIndex, offsetBy: 7) String(str[startIndex...endIndex]) // "Strin"
前n个字符
let startIndex = str.index(str.startIndex, offsetBy: 3) String(str[..<startIndex]) // "My "
最后n个字符
let startIndex = str.index(str.startIndex, offsetBy: 3) String(str[startIndex...]) // "String"
Swift 2和3
str = "My String"
**string在索引**
Swift 2
let charAtIndex = String(str[str.startIndex.advancedBy(3)]) // charAtIndex = "S"
Swift 3
str[str.index(str.startIndex, offsetBy: 3)]
子索引从索引到索引
Swift 2
let subStr = str[str.startIndex.advancedBy(3)...str.startIndex.advancedBy(7)] // subStr = "Strin"
Swift 3
str[str.index(str.startIndex, offsetBy: 3)...str.index(str.startIndex, offsetBy: 7)]
前n个字符
let first2Chars = String(str.characters.prefix(2)) // first2Chars = "My"
最后n个字符
let last3Chars = String(str.characters.suffix(3)) // last3Chars = "ing"
Swift 2.0的Xcode 7转基因种子
var text = "Hello, world!" let firstChar = text[text.startIndex.advancedBy(0)] // "H"
对于第n个字符,用n-1replace0。
编辑:Swift 3.0
text[text.index(text.startIndex, offsetBy: 0)]
NB有更简单的方法来抓取string中的某些字符
例如let firstChar = text.characters.first
如果您看到Cannot subscript a value of type 'String'...
使用此扩展名:
Swift 3
extension String { subscript (i: Int) -> Character { return self[self.characters.index(self.startIndex, offsetBy: i)] } subscript (i: Int) -> String { return String(self[i] as Character) } subscript (r: Range<Int>) -> String { let start = index(startIndex, offsetBy: r.lowerBound) let end = index(startIndex, offsetBy: r.upperBound) return self[start..<end] } subscript (r: ClosedRange<Int>) -> String { let start = index(startIndex, offsetBy: r.lowerBound) let end = index(startIndex, offsetBy: r.upperBound) return self[start...end] } }
Swift 2.3
extension String { subscript(integerIndex: Int) -> Character { let index = advance(startIndex, integerIndex) return self[index] } subscript(integerRange: Range<Int>) -> String { let start = advance(startIndex, integerRange.startIndex) let end = advance(startIndex, integerRange.endIndex) let range = start..<end return self[range] } }
来源: http : //oleb.net/blog/2014/07/swift-strings/
Swift 2.2解决scheme:
下面的扩展在Xcode 7中起作用,这是这个解决scheme和Swift 2.0语法转换的结合。
extension String { subscript(integerIndex: Int) -> Character { let index = startIndex.advancedBy(integerIndex) return self[index] } subscript(integerRange: Range<Int>) -> String { let start = startIndex.advancedBy(integerRange.startIndex) let end = startIndex.advancedBy(integerRange.endIndex) let range = start..<end return self[range] } }
顺便说一下,有一些函数可以直接应用于string的字符链表示,如下所示:
var string = "Hello, playground" let firstCharacter = string.characters.first // returns "H" let lastCharacter = string.characters.last // returns "d"
结果是字符types,但可以将其转换为string。
或这个:
let reversedString = String(string.characters.reverse()) // returns "dnuorgyalp ,olleH"
🙂
swiftstring类不提供在特定索引处获取字符的能力,因为它支持UTF字符。 内存中的UTF字符的可变长度使得直接跳转到不可能的字符。 这意味着您必须每次手动循环string。
您可以扩展string来提供一个方法,将遍历字符,直到您所需的索引
extension String { func characterAtIndex(index: Int) -> Character? { var cur = 0 for char in self { if cur == index { return char } cur++ } return nil } } myString.characterAtIndex(0)!
我只是有同样的问题。 只需做到这一点:
var aString: String = "test" var aChar:unichar = (aString as NSString).characterAtIndex(0)
我的解决scheme是在一行,假设cadena是string,4是你想要的第n个位置:
let character = cadena[advance(cadena.startIndex, 4)]
简单…我想Swift将在未来版本中包含更多有关子串的内容。
为了提供主题和显示swift下标的可能性,这里有一个小string“substring-toolbox”下标为基础
这些方法是安全的,永远不会超越string索引
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 ???
第一个(str)//检索第一个字母
更多信息: http : //sketchytech.blogspot.com/2014/08/swift-pure-swift-method-for-returning.html
更新swift 2.0 subString
public extension String { public subscript (i: Int) -> String { return self.substringWithRange(self.startIndex..<self.startIndex.advancedBy(i + 1)) } public subscript (r: Range<Int>) -> String { get { return self.substringWithRange(self.startIndex.advancedBy(r.startIndex)..<self.startIndex.advancedBy(r.endIndex)) } } }
我认为得到第一个字符的快速答案可能是:
let firstCharacter = aString[aString.startIndex]
这是如此优雅和性能比:
let firstCharacter = Array(aString.characters).first
但是,如果你想操纵和使用string做更多的操作,你可以认为创build一个扩展..这是一个扩展与这种方法,这是非常相似,已经发布在这里:
extension String { var length : Int { return self.characters.count } subscript(integerIndex: Int) -> Character { let index = startIndex.advancedBy(integerIndex) return self[index] } subscript(integerRange: Range<Int>) -> String { let start = startIndex.advancedBy(integerRange.startIndex) let end = startIndex.advancedBy(integerRange.endIndex) let range = start..<end return self[range] }
}
但这是一个可怕的想法!
下面的扩展是非常低效的。 每次使用整数访问string时,都会运行O(n)函数以提前启动索引。 在另一个线性循环内部运行一个线性循环意味着这个for循环意外地是O(n2) – 随着string长度的增加,这个循环所花费的时间以二次方式增加。
而不是你可以使用字符的string集合。
Swift 3:另一个解决scheme(在操场上testing)
extension String { func substr(_ start:Int, length:Int=0) -> String? { guard start > -1 else { return nil } let count = self.characters.count - 1 guard start <= count else { return nil } let startOffset = max(0, start) let endOffset = length > 0 ? min(count, startOffset + length - 1) : count return self[self.index(self.startIndex, offsetBy: startOffset)...self.index(self.startIndex, offsetBy: endOffset)] } }
用法:
let txt = "12345" txt.substr(-1) //nil txt.substr(0) //"12345" txt.substr(0, length: 0) //"12345" txt.substr(1) //"2345" txt.substr(2) //"345" txt.substr(3) //"45" txt.substr(4) //"5" txt.substr(6) //nil txt.substr(0, length: 1) //"1" txt.substr(1, length: 1) //"2" txt.substr(2, length: 1) //"3" txt.substr(3, length: 1) //"4" txt.substr(3, length: 2) //"45" txt.substr(3, length: 3) //"45" txt.substr(4, length: 1) //"5" txt.substr(4, length: 2) //"5" txt.substr(5, length: 1) //nil txt.substr(5, length: -1) //nil txt.substr(-1, length: -1) //nil
Swift的String
types不提供characterAtIndex
方法,因为Unicodestring有多种编码方式。 你用UTF8,UTF16还是其他的?
您可以通过检索String.utf8
和String.utf16
属性来访问CodeUnit
集合。 您还可以通过检索String.unicodeScalars
属性来访问UnicodeScalar
集合。
本着NSString
的实现精神,我返回一个unichar
types。
extension String { func characterAtIndex(index:Int) -> unichar { return self.utf16[index] } // Allows us to use String[index] notation subscript(index:Int) -> unichar { return characterAtIndex(index) } } let text = "Hello Swift!" let firstChar = text[0]
一个类似python的解决scheme,它允许你使用负向索引,
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的切片符号转换是值得的
您也可以将string转换为像这样的字符数组:
let text = "My Text" let index = 2 let charSequence = text.unicodeScalars.map{ Character($0) } let char = charSequence[index]
这是在指定的索引时间内获取char的方法。
下面的例子不是在一段时间内运行,而是需要线性时间。 所以如果你有很多索引searchstring使用上面的方法。
let char = text[text.startIndex.advancedBy(index)]
在Swift 3
let mystring = "Hello, world!" let stringToArray = Array(mystring.characters) let indices = (stringToArray.count)-1 print(stringToArray[0]) //H print(stringToArray[indices]) //!
使用字符将完成这项工作。 您可以快速将string转换为可由CharacterView方法操纵的字符数组。
例:
let myString = "Hello World!" let myChars = myString.characters
(完整CharacterView文档)
(在Swift 3中testing)
斯威夫特4
范围和部分范围使用String
的indices
属性的下标
作为@LeoDabus好的答案的变种 ,我们可以添加一个额外的扩展到DefaultBidirectionalIndices
,目的是允许我们回落在String
的indices
属性时,为后者实现自定义下标(通过Int
专用范围和部分范围)。
extension DefaultBidirectionalIndices { subscript(at: Int) -> Elements.Index { return index(startIndex, offsetBy: at) } } // Moving the index(_:offsetBy:) to an extension yields slightly // briefer implementations for these String extensions. extension String { subscript(r: CountableClosedRange<Int>) -> SubSequence { return self[indices[r.lowerBound]...indices[r.upperBound]] } subscript(r: CountablePartialRangeFrom<Int>) -> SubSequence { return self[indices[r.lowerBound]...] } subscript(r: PartialRangeThrough<Int>) -> SubSequence { return self[...indices[r.upperBound]] } subscript(r: PartialRangeUpTo<Int>) -> SubSequence { return self[..<indices[r.upperBound]] } } let str = "foo bar baz bax" print(str[4...6]) // "bar" print(str[4...]) // "bar baz bax" print(str[...6]) // "foo bar" print(str[..<6]) // "foo ba"
感谢@LeoDabus指向我的方向使用indices
属性作为(其他) String
下标的替代方法!
你可以使用SwiftString( https://github.com/amayne/SwiftString )来做到这一点。
"Hello, world!"[0] // H "Hello, world!"[0...4] // Hello
免责声明:我写了这个扩展名
Swift 3
extension String { public func charAt(_ i: Int) -> Character { return self[self.characters.index(self.startIndex, offsetBy: i)] } public subscript (i: Int) -> String { return String(self.charAt(i) as Character) } public subscript (r: Range<Int>) -> String { return substring(with: self.characters.index(self.startIndex, offsetBy: r.lowerBound)..<self.characters.index(self.startIndex, offsetBy: r.upperBound)) } public subscript (r: CountableClosedRange<Int>) -> String { return substring(with: self.characters.index(self.startIndex, offsetBy: r.lowerBound)..<self.characters.index(self.startIndex, offsetBy: r.upperBound)) } }
用法
let str = "Hello World" let sub = str[0...4]
有用的编程技巧和窍门(由我撰写)
我想指出的是,如果你有一个很大的string,并且需要从中随机访问很多字符,你可能要花费额外的内存开销,并将string转换为一个数组以获得更好的性能:
// 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]) }
在没有扩展到String类的Swift 3中,尽可能简单!
let myString = "abcedfg" let characterLocationIndex = myString.index(myString.startIndex, offsetBy: 3) let myCharacter = myString[characterLocationIndex]
在这个例子中,myCharacter是“3”。
Swift3
您可以使用下标语法来访问特定string索引处的字符。
let greeting = "Guten Tag!" let index = greeting.index(greeting.startIndex, offsetBy: 7) greeting[index] // a
允许负指数
它总是有用的,而不是总是写string[string.length - 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
对于更彻底的程序员来说:在这个扩展中包含一个空string的guard
subscript (i: Int) -> Character { guard self.count != 0 else { return '' } ... } subscript (r: Range<Int>) -> String { guard self.count != 0 else { return "" } ... }
- 我应该如何删除string中的所有空格? – 迅速
- dyld:Library未加载:@ rpath / libswiftCore.dylib / Image not found
- SourceKitService终止
- 在Swift中访问类中的静态variables
- Swift:在索引处replaceString数组
- 如何在Swift项目中使用Objective-C Cocoapods?
- 使用Alamofire在iOS Swift中使用MultipartFormData发送POST参数
- 在Swift String中查找字符索引
- libc ++ abi.dylib:以NSException(lldb)types的未捕获exception终止