Получить N-й символ строки на языке программирования Swift
Как я могу получить N-й символ строки? Я попробовал кронштейн ([]
) accessor без везения.
var string = "Hello, world!"
var firstChar = string[0] // Throws error
30 ответов
внимание: см. Лев Dabus-ответ для правильной реализации для Swift 4.
Swift 4
на Substring
тип был введен в Swift 4, чтобы сделать подстроки
быстрее и эффективнее, разделяя хранилище с исходной строкой, так что это то, что должны возвращать функции индекса.
попробовать здесь
extension String {
subscript (i: Int) -> Character {
return self[index(startIndex, offsetBy: i)]
}
subscript (bounds: CountableRange<Int>) -> Substring {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ..< end]
}
subscript (bounds: CountableClosedRange<Int>) -> Substring {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ... end]
}
subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
return self[start ... end]
}
subscript (bounds: PartialRangeThrough<Int>) -> Substring {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ... end]
}
subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ..< end]
}
}
extension Substring {
subscript (i: Int) -> Character {
return self[index(startIndex, offsetBy: i)]
}
subscript (bounds: CountableRange<Int>) -> Substring {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ..< end]
}
subscript (bounds: CountableClosedRange<Int>) -> Substring {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ... end]
}
subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
return self[start ... end]
}
subscript (bounds: PartialRangeThrough<Int>) -> Substring {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ... end]
}
subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ..< end]
}
}
преобразование Substring
на String
, вы можете просто
do String(string[0..2])
, но вы должны делать это только если
вы планируете сохранить подстроку. В противном случае, это больше
эффективно держать его Substring
.
было бы здорово, если бы кто-то мог придумать хороший способ слияния
эти два расширения в одно. Я попытался расширить StringProtocol
без успеха, потому что index
метод не существует.
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)]
}
}
почему это не встроенный?
Apple предоставляет следующее объяснение (найти здесь):
подписка на строки с целыми числами недоступна.
понятие " the
i
тый символ в строке" имеет различные интерпретации в разных библиотеках и системы комплектующие. Следует выбрать правильное толкование в соответствии с прецедентом использования и задействованными API, soString
нельзя индексного с целое число.Swift предоставляет несколько различных способов доступа к символу данные, хранящиеся внутри строк.
String.utf8
собрание блоков кода UTF-8 в строка. Используйте этот API при преобразовании строки в UTF-8. Большинство POSIX API обрабатывают строки в терминах кодовых единиц UTF-8.
String.utf16
собрание блоков кода UTF-16 внутри строка. Большинство строк процесса API Cocoa и Cocoa touch в термины блоков кода UTF-16. Например, экземплярыNSRange
используется сNSAttributedString
иNSRegularExpression
хранить смещения и длины подстроки в термины блоков кода UTF-16.
String.unicodeScalars
представляет собой набор скаляров Юникода. Использовать этот API при выполнении низкоуровневых манипуляций символьных данных.
String.characters
- это сборник графема кластеры, которые являются приближением воспринимаемых пользователем письмена.обратите внимание, что при обработке строк, содержащих читаемый текст, следует избегать обработки символов в наибольшей степени вероятный. Вместо этого используйте высокоуровневые алгоритмы Юникода, чувствительные к локали, например,
String.localizedStandardCompare()
,String.localizedLowercaseString
,String.localizedStandardRangeOfString()
etc.
строка поддерживает индекс (доступ с [ ] ) из коробки:
Swift 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"
... ваше расширение строки должно быть похоже (полностью протестировано):
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
и получить подстроки, используя их.
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]
обратите внимание, что вы никогда не можете использовать индекс (или диапазон), созданный из одной строки в другую строку
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]
Swift 4.1 или более поздней версии
вы можете расширить StringProtocol Swift 4, чтобы сделать индекс доступным также для подстрок. Отмечать:
Из-за предложения SE-0191 расширение только IndexDistance == Int
можно удалить:
extension StringProtocol {
var string: String { return String(self) }
subscript(offset: Int) -> Element {
return self[index(startIndex, offsetBy: offset)]
}
subscript(_ range: CountableRange<Int>) -> SubSequence {
return prefix(range.lowerBound + range.count)
.suffix(range.count)
}
subscript(range: CountableClosedRange<Int>) -> SubSequence {
return prefix(range.lowerBound + range.count)
.suffix(range.count)
}
subscript(range: PartialRangeThrough<Int>) -> SubSequence {
return prefix(range.upperBound.advanced(by: 1))
}
subscript(range: PartialRangeUpTo<Int>) -> SubSequence {
return prefix(range.upperBound)
}
subscript(range: PartialRangeFrom<Int>) -> SubSequence {
return suffix(Swift.max(0, count - range.lowerBound))
}
}
extension Substring {
var string: String { return String(self) }
}
тестирование
let test = "Hello USA !!! Hello Brazil !!!"
test[safe: 10] // ""
test[11] // "!"
test[10...] // "!!! Hello Brazil !!!"
test[10..<12] // "!"
test[10...12] // "!!"
test[...10] // "Hello USA "
test[..<10] // "Hello USA "
test.first // "H"
test.last // "!"
// Subscripting the Substring
test[...][...3] // "Hell"
// Note that they all return a Substring of the original String.
// To create a new String you need to add .string as follow
test[10...].string // "!!! Hello Brazil !!!"
Swift 4
let str = "My 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"
**Строка В Индексе**
Swift 2
let charAtIndex = String(str[str.startIndex.advancedBy(3)]) // charAtIndex = "S"
Swift 3
str[str.index(str.startIndex, offsetBy: 3)]
подстрока fromIndex toIndex
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 GM Seed
var text = "Hello, world!"
let firstChar = text[text.startIndex.advancedBy(0)] // "H"
для n-го символа заменить 0 на n-1.
Edit: Swift 3.0
text[text.index(text.startIndex, offsetBy: 0)]
n.b. есть более простые способы захвата определенных символов в строке
например 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]
}
}
Swift 2.2 Решение:
следующее расширение работает в Xcode 7, это сочетание этой решение и преобразование синтаксиса 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]
}
}
класс swift string не предоставляет возможность получить символ в определенном индексе из-за его собственной поддержки символов UTF. Переменная длина символа UTF в памяти делает невозможным переход непосредственно к символу. Это означает, что вы должны вручную перебирать строку каждый раз.
вы можете расширить строку, чтобы предоставить метод, который будет проходить через символы до нужного индекса
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 string = "Hello, playground"
let firstCharacter = string.characters.first // returns "H"
let lastCharacter = string.characters.last // returns "d"
результат имеет тип Character, но вы можете привести его к строке.
или такой:
let reversedString = String(string.characters.reverse())
// returns "dnuorgyalp ,olleH"
: -)
Swift 4
String(Array(stringToIndex)[index])
Это, вероятно, лучший способ решить эту проблему один раз. Вероятно, вы хотите сначала привести строку в виде массива, а затем снова привести результат в виде строки. В противном случае вместо строки будет возвращен символ.
пример String(Array("HelloThere")[1])
вернет "e" в виде строки.
(Array("HelloThere")[1]
вернет" e " в качестве символа.
Swift не позволяет индексировать строки как массивы, но это получает работу, силовом стиле.
У меня была та же проблема. Просто сделайте это:
var aString: String = "test"
var aChar:unichar = (aString as NSString).characterAtIndex(0)
мое решение находится в одной строке, предположим, что cadena-это строка, а 4-это N-я позиция, которую вы хотите:
let character = cadena[advance(cadena.startIndex, 4)]
простой... Я полагаю, что Swift будет включать больше вещей о подстроках в будущих версиях.
мое очень простое решение:
let myString = "Test string"
let index = 0
let firstCharacter = myString[String.Index(encodedOffset: index)]
чтобы накормить тему и показать возможности Swift subscript, вот небольшая строка" substring-toolbox " subscript based
эти методы безопасны и никогда не переходят через строковые индексы
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 ???
обновление для подстроки swift 2.0
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
но.. если вы хотите манипулировать и выполнять больше операций со строками, вы можете подумать о создании расширения..вот одно расширение с таким подходом, оно очень похоже на то, что уже опубликовано здесь:
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]
}
}
НО ЭТО УЖАСНАЯ ИДЕЯ!!
расширение ниже ужасно неэффективный. Каждый раз, когда к строке обращаются с целым числом, запускается функция O(n) для продвижения ее начального индекса. Запуск линейного цикла внутри другого линейного цикла означает, что это для цикла случайно O(n2) - по мере увеличения длины строки время, которое занимает этот цикл, увеличивается квадратично.
вместо этого вы можете использовать коллекцию строк символов.
В Swift 3
let mystring = "Hello, world!"
let stringToArray = Array(mystring.characters)
let indices = (stringToArray.count)-1
print(stringToArray[0]) //H
print(stringToArray[indices]) //!
Swift 3: другое решение (протестировано на игровой площадке)
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
Swift3
вы можете использовать синтаксис индекса для доступа к символу в определенном строковом индексе.
let greeting = "Guten Tag!"
let index = greeting.index(greeting.startIndex, offsetBy: 7)
greeting[index] // a
или мы можем сделать расширение строку Swift 4
extension String {
func getCharAtIndex(_ index: Int) -> Character {
return self[self.index(self.startIndex, offsetBy: index)]
}
}
использование:
let foo = "ABC123"
foo.getCharAtIndex(2) //C
Swift 4
диапазон и частичный диапазон подписки с помощью String
' s indices
свойства
как вариант @LeoDabus хороший ответ, мы можем добавить дополнительное расширение к DefaultBidirectionalIndices
С целью позволить нам отступить на indices
собственность String
при реализации пользовательских индексов (по 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
индексации!
Swift 4.2.
В Swift 4.2,DefaultBidirectionalIndices
был осужден в пользу DefaultIndices
.
Свифт String
тип не обеспечивает characterAtIndex
метод, потому что существует несколько способов кодирования строки Unicode. Вы собираетесь с UTF8, UTF16 или что-то еще?
вы можете получить доступ к CodeUnit
коллекции путем извлечения String.utf8
и String.utf16
свойства. Вы также можете получить доступ к UnicodeScalar
сбор, извлекая String.unicodeScalars
собственность.
в духе NSString
реализация, я возвращаю unichar
тип.
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-подобное решение, которое позволяет использовать отрицательный индекс,
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
вы также можете преобразовать строку в массив таких символов:
let text = "My Text"
let index = 2
let charSequence = text.unicodeScalars.map{ Character() }
let char = charSequence[index]
Это способ получить char по указанному индексу за постоянное время.
приведенный ниже пример не выполняется в постоянное время, но требует линейного времени. Поэтому, если у вас есть много поиска в строке по индексу, используйте метод выше.
let char = text[text.startIndex.advancedBy(index)]
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]
полезные советы и рекомендации по программированию (написанные мной)
С помощью символы сделал бы работу. Вы можете быстро преобразовать строка к массиву символов, которыми можно манипулировать с помощью методов CharacterView.
пример:
let myString = "Hello World!"
let myChars = myString.characters
(full CharacterView doc)
(протестировано в Swift 3)
есть альтернатива, объясненная в строка манифеста
extension String : BidirectionalCollection {
subscript(i: Index) -> Character { return characters[i] }
}
получить первую букву:
first(str) // retrieve first letter
подробнее здесь: http://sketchytech.blogspot.com/2014/08/swift-pure-swift-method-for-returning.html
Get & Set Subscript (Строка И Подстрока) - Swift 4.1
Swift 4.1, Xcode 9.3
Я основал свой ответ от @alecarlson'ы ответ.
Единственная большая разница вы можете приобрести Substring
или String
вернулся (а в некоторых случаях, один Character
). вы можете get
и set
подстрочный.
Наконец, мой более громоздкий и более длинный, чем @alecarlsonи как таковой, я предлагаю вам поставить его в исходном файле.
:
public extension String {
public subscript (i: Int) -> Character {
get {
return self[index(startIndex, offsetBy: i)]
}
set (c) {
let n = index(startIndex, offsetBy: i)
replaceSubrange(n...n, with: "\(c)")
}
}
public subscript (bounds: CountableRange<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ..< end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ..< end, with: s)
}
}
public subscript (bounds: CountableClosedRange<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ... end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
return self[start ... end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: PartialRangeThrough<Int>) -> Substring {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ... end]
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ... end, with: s)
}
}
public subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ..< end]
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ..< end, with: s)
}
}
public subscript (i: Int) -> String {
get {
return "\(self[index(startIndex, offsetBy: i)])"
}
set (c) {
let n = index(startIndex, offsetBy: i)
self.replaceSubrange(n...n, with: "\(c)")
}
}
public subscript (bounds: CountableRange<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[start ..< end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ..< end, with: s)
}
}
public subscript (bounds: CountableClosedRange<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[start ... end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: CountablePartialRangeFrom<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
return "\(self[start ... end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: PartialRangeThrough<Int>) -> String {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[startIndex ... end])"
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ... end, with: s)
}
}
public subscript (bounds: PartialRangeUpTo<Int>) -> String {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[startIndex ..< end])"
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ..< end, with: s)
}
}
public subscript (i: Int) -> Substring {
get {
return Substring("\(self[index(startIndex, offsetBy: i)])")
}
set (c) {
let n = index(startIndex, offsetBy: i)
replaceSubrange(n...n, with: "\(c)")
}
}
}
public extension Substring {
public subscript (i: Int) -> Character {
get {
return self[index(startIndex, offsetBy: i)]
}
set (c) {
let n = index(startIndex, offsetBy: i)
replaceSubrange(n...n, with: "\(c)")
}
}
public subscript (bounds: CountableRange<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ..< end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ..< end, with: s)
}
}
public subscript (bounds: CountableClosedRange<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[start ... end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: CountablePartialRangeFrom<Int>) -> Substring {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
return self[start ... end]
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: PartialRangeThrough<Int>) -> Substring {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ... end]
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ..< end, with: s)
}
}
public subscript (bounds: PartialRangeUpTo<Int>) -> Substring {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return self[startIndex ..< end]
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ..< end, with: s)
}
}
public subscript (i: Int) -> String {
get {
return "\(self[index(startIndex, offsetBy: i)])"
}
set (c) {
let n = index(startIndex, offsetBy: i)
replaceSubrange(n...n, with: "\(c)")
}
}
public subscript (bounds: CountableRange<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[start ..< end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ..< end, with: s)
}
}
public subscript (bounds: CountableClosedRange<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[start ... end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: CountablePartialRangeFrom<Int>) -> String {
get {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
return "\(self[start ... end])"
}
set (s) {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(endIndex, offsetBy: -1)
replaceSubrange(start ... end, with: s)
}
}
public subscript (bounds: PartialRangeThrough<Int>) -> String {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[startIndex ... end])"
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ... end, with: s)
}
}
public subscript (bounds: PartialRangeUpTo<Int>) -> String {
get {
let end = index(startIndex, offsetBy: bounds.upperBound)
return "\(self[startIndex ..< end])"
}
set (s) {
let end = index(startIndex, offsetBy: bounds.upperBound)
replaceSubrange(startIndex ..< end, with: s)
}
}
public subscript (i: Int) -> Substring {
get {
return Substring("\(self[index(startIndex, offsetBy: i)])")
}
set (c) {
let n = index(startIndex, offsetBy: i)
replaceSubrange(n...n, with: "\(c)")
}
}
}