在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的Stringtypes不提供characterAtIndex方法,因为Unicodestring有多种编码方式。 你用UTF8,UTF16还是其他的?

您可以通过检索String.utf8String.utf16属性来访问CodeUnit集合。 您还可以通过检索String.unicodeScalars属性来访问UnicodeScalar集合。

本着NSString的实现精神,我返回一个unichartypes。

 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

范围和部分范围使用Stringindices属性的下标

作为@LeoDabus好的答案的变种 ,我们可以添加一个额外的扩展到DefaultBidirectionalIndices ,目的是允许我们回落在Stringindices属性时,为后者实现自定义下标(通过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 

访问https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html

允许负指数

它总是有用的,而不是总是写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 "" } ... }