¿Cómo funciona la subcadena de cadena en Swift?

354

He estado actualizando algunos de mis códigos y respuestas anteriores con Swift 3, pero cuando llegué a Swift Strings e Indexing con subcadenas, las cosas se volvieron confusas.

Específicamente estaba intentando lo siguiente:

let str = "Hello, playground"
let prefixRange = str.startIndex..<str.startIndex.advancedBy(5)
let prefix = str.substringWithRange(prefixRange)

donde la segunda línea me daba el siguiente error

El valor del tipo 'String' no tiene miembro 'substringWithRange'

Veo que Stringtiene los siguientes métodos ahora:

str.substring(to: String.Index)
str.substring(from: String.Index)
str.substring(with: Range<String.Index>)

Al principio me confundieron mucho, así que comencé a jugar con el índice y el rango . Esta es una pregunta y respuesta de seguimiento para la subcadena. Añado una respuesta a continuación para mostrar cómo se usan.

Suragch
fuente
2
Para aquellos que desean obtener la subcadena de la cadena stackoverflow.com/q/32305891/468724
Inder Kumar Rathore el
o cadena de subíndice o subcadena stackoverflow.com/questions/24092884/…
Leo Dabus

Respuestas:

832

ingrese la descripción de la imagen aquí

Todos los siguientes ejemplos usan

var str = "Hello, playground"

Swift 4

Las cadenas obtuvieron una revisión bastante grande en Swift 4. Cuando obtienes una subcadena de una cadena ahora, obtienes un Substringtipo de regreso en lugar de unString . ¿Por qué es esto? Las cadenas son tipos de valor en Swift. Eso significa que si usa una Cadena para hacer una nueva, entonces debe copiarse. Esto es bueno para la estabilidad (nadie más lo va a cambiar sin su conocimiento) pero malo para la eficiencia.

Una subcadena, por otro lado, es una referencia a la cadena original de la que proviene. Aquí hay una imagen de la documentación que ilustra eso.

No se necesita copiar, por lo que es mucho más eficiente de usar. Sin embargo, imagina que tienes una subcadena de diez caracteres de una cadena de un millón de caracteres. Debido a que la Subcadena hace referencia a la Cadena, el sistema tendría que retener la Cadena completa mientras la Subcadena esté alrededor. Por lo tanto, cada vez que termine de manipular su Subcadena, conviértala en una Cadena.

let myString = String(mySubstring)

Esto copiará solo la subcadena y la memoria que contiene la antigua cadena puede recuperarse . Las subcadenas (como tipo) están destinadas a ser de corta duración.

Otra gran mejora en Swift 4 es que las cadenas son colecciones (nuevamente). Eso significa que cualquier cosa que pueda hacer a una Colección, puede hacerlo a una Cadena (usar subíndices, iterar sobre los caracteres, filtrar, etc.).

Los siguientes ejemplos muestran cómo obtener una subcadena en Swift.

Obteniendo subcadenas

Usted puede obtener una subcadena de una cadena mediante el uso de subíndices o una serie de otros métodos (por ejemplo, prefix, suffix, split). Sin embargo, aún necesita usar String.Indexy no un Intíndice para el rango. (Ver mi otra respuesta si necesita ayuda con eso).

Comienzo de una cuerda

Puede usar un subíndice (tenga en cuenta el rango unilateral Swift 4):

let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str[..<index] // Hello

o prefix:

let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str.prefix(upTo: index) // Hello

o incluso más fácil:

let mySubstring = str.prefix(5) // Hello

Fin de una cuerda.

Usando subíndices:

let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str[index...] // playground

o suffix:

let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str.suffix(from: index) // playground

o incluso más fácil:

let mySubstring = str.suffix(10) // playground

Tenga en cuenta que al usar el suffix(from: index)tuve que contar desde el final usando -10. Eso no es necesario cuando solo se usa suffix(x), que solo toma los últimos xcaracteres de una Cadena.

Rango en una cuerda

Nuevamente, simplemente usamos subíndices aquí.

let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let range = start..<end

let mySubstring = str[range]  // play

Convertir SubstringaString

No olvide que, cuando esté listo para guardar su subcadena, debe convertirla en a Stringpara que se pueda limpiar la memoria de la cadena anterior.

let myString = String(mySubstring)

¿Usando una Intextensión de índice?

Dudo en usar una Intextensión de índice basada después de leer el artículo Strings in Swift 3 de Airspeed Velocity y Ole Begemann. Aunque en Swift 4, las cadenas son colecciones, el equipo de Swift no ha utilizado Intíndices a propósito . Está quieto String.Index. Esto tiene que ver con que los caracteres Swift están compuestos por un número variable de puntos de código Unicode. El índice real tiene que calcularse de manera única para cada cadena.

Tengo que decir que espero que el equipo de Swift encuentre una forma de abstraerse String.Indexen el futuro. Pero hasta ellos elijo usar su API. Me ayuda a recordar que las manipulaciones de cadenas no son simples Intbúsquedas de índice.

Suragch
fuente
99
Gracias por la desctripción. Mejoras merecidas. Apple ha complicado demasiado esto. La subcadena debería ser tan fácil como string.substring [de ... a].
Teddy
Muy buena explicación. excepto una pequeña cosa garbage collected;-) Espero que la gente aquí sepa que no hay recolección de basura en Swift.
Christian Anchor Dampf
@ChristianAnchorDampf, gracias por tomarse el tiempo para comentar. Saqué la recolección de basura. ¿Cómo es la nueva redacción?
Suragch
¡Qué respuesta tan asombrosa señor!
davidev
194

Estoy realmente frustrado con el modelo de acceso a cadenas de Swift: todo tiene que ser un Index. Todo lo que quiero es acceder al carácter i-ésimo de la cadena usando Int, no el índice torpe y avanzar (que cambia con cada lanzamiento importante). Entonces hice una extensión para String:

extension String {
    func index(from: Int) -> Index {
        return self.index(startIndex, offsetBy: from)
    }

    func substring(from: Int) -> String {
        let fromIndex = index(from: from)
        return String(self[fromIndex...])
    }

    func substring(to: Int) -> String {
        let toIndex = index(from: to)
        return String(self[..<toIndex])
    }

    func substring(with r: Range<Int>) -> String {
        let startIndex = index(from: r.lowerBound)
        let endIndex = index(from: r.upperBound)
        return String(self[startIndex..<endIndex])
    }
}

let str = "Hello, playground"
print(str.substring(from: 7))         // playground
print(str.substring(to: 5))           // Hello
print(str.substring(with: 7..<11))    // play
Código diferente
fuente
55
Los índices son muy útiles porque un carácter puede tener más de un byte. Pruebalet str = "🇨🇭🇩🇪🇺🇸Hello" print(str.substring(to: 2))
vadian
112
Sí, entiendo que un carácter (es decir, un clúster de grafema extendido ) puede tomar varios bytes. Mi frustración es la razón por la que tenemos que usar el método de avance de índice detallado para acceder a los caracteres de una cadena. ¿Por qué el equipo de Swift no puede simplemente agregar algunas sobrecargas a la Biblioteca Central para abstraerlo? Si escribo str[5], quiero acceder al carácter en el índice 5, sea cual sea ese carácter o cuántos bytes se necesitan. ¿No se trata Swift de la productividad del desarrollador?
Código diferente
66
@ RenniePet Creo que Apple reconoce el problema y se avecinan cambios. Según la página Swift Evolution en GitHub: "Swift 4 busca hacer que las cadenas sean más potentes y fáciles de usar, al tiempo que conserva la corrección Unicode de forma predeterminada". Es vago, pero mantengamos nuestras esperanzas
código diferente
3
@CodeDifferent ¿por qué Apple no agregó el acceso de caracteres de subíndice? Para que la gente entienda que es algo malo hacer. Básicamente, si lo hicieras para i en 0..string.count usando subíndices que serían de doble bucle, porque debajo del índice del capó tiene que pasar por cada byte de cadena para descubrir cuál es el siguiente carácter. Si realiza un bucle con el índice, itera sobre la cadena solo una vez. Por cierto, odio esto yo mismo, pero ese es el razonamiento detrás de que el subíndice no está disponible en cadena de forma rápida.
Raimundas Sakalauskas
44
@RaimundasSakalauskas ese argumento no pasa desapercibido para mí. C # tiene tanto la corrección Unicode como la suscripción de enteros, lo cual es realmente conveniente. En Swift 1, Apple quería que los desarrolladores lo usaran countElement(str)para encontrar la longitud. En Swift 3, Apple hizo que la cadena no se ajustara Sequencey obligó a todos a usarla str.characters. Estos muchachos no tienen miedo de hacer cambios. Su terquedad en la suscripción de enteros es realmente difícil de entender
Code Different
103

Extensión Swift 5:

extension String {
    subscript(_ range: CountableRange<Int>) -> String {
        let start = index(startIndex, offsetBy: max(0, range.lowerBound))
        let end = index(start, offsetBy: min(self.count - range.lowerBound, 
                                             range.upperBound - range.lowerBound))
        return String(self[start..<end])
    }

    subscript(_ range: CountablePartialRangeFrom<Int>) -> String {
        let start = index(startIndex, offsetBy: max(0, range.lowerBound))
         return String(self[start...])
    }
}

Uso:

let s = "hello"
s[0..<3] // "hel"
s[3...]  // "lo"

O unicode:

let s = "😎🤣😋"
s[0..<1] // "😎"
Lou Zell
fuente
2
Mucho mejor, ¡gracias por publicar esta extensión! Creo que viniendo de Python, Swift es mucho más difícil de lo necesario para acostumbrarse. Parece que para las personas que van en la otra dirección del Objetivo C a Swift hay una confirmación más positiva.
user3064009
1
@Leon, acabo de eliminarlo. Antes de 4.1, countsolo estaba disponible enself.characters
Lou Zell
1
¿Hay alguna trampa para tener en cuenta con esta extensión en particular? ¿Por qué Apple no hizo algo como esto?
Andz
1
@Andz es muy ineficiente. Comienza desde el principio de la cadena, dos veces, y tiene que analizar cada carácter desde allí para "rango", dos veces.
kareman
3
También necesitará agregar una extensión que tome unCountableClosedRange<Int> si desea escribir, por ejemplo s[0...2].
Chris Frederick
24

Swift 4 y 5:

extension String {
  subscript(_ i: Int) -> String {
    let idx1 = index(startIndex, offsetBy: i)
    let idx2 = index(idx1, offsetBy: 1)
    return String(self[idx1..<idx2])
  }

  subscript (r: Range<Int>) -> String {
    let start = index(startIndex, offsetBy: r.lowerBound)
    let end = index(startIndex, offsetBy: r.upperBound)
    return String(self[start ..< end])
  }

  subscript (r: CountableClosedRange<Int>) -> String {
    let startIndex =  self.index(self.startIndex, offsetBy: r.lowerBound)
    let endIndex = self.index(startIndex, offsetBy: r.upperBound - r.lowerBound)
    return String(self[startIndex...endIndex])
  }
}

Cómo usarlo:

"abcde" [0] -> "a"

"abcde" [0 ... 2] -> "abc"

"abcde" [2 .. <4] -> "cd"

ROCHDI de sopa
fuente
20

Swift 4

En rápido 4 se Stringajusta a Collection. En lugar de substring, ahora deberíamos usar una subscript.Así que si usted quiere cortar sólo la palabra "play"de "Hello, playground", usted podría hacerlo de esta manera:

var str = "Hello, playground"
let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let result = str[start..<end] // The result is of type Substring

Es interesante saber que hacerlo te dará un en Substringlugar de un String. Esto es rápido y eficiente, ya que Substringcomparte su almacenamiento con la cadena original. Sin embargo, compartir memoria de esta manera también puede conducir fácilmente a pérdidas de memoria.

Es por eso que debe copiar el resultado en una nueva Cadena, una vez que desee limpiar la Cadena original. Puedes hacer esto usando el constructor normal:

let newString = String(result)

Puede encontrar más información sobre la nueva Substringclase en la [documentación de Apple]. 1

Entonces, si por ejemplo obtienes un Rangecomo resultado de un NSRegularExpression, puedes usar la siguiente extensión:

extension String {

    subscript(_ range: NSRange) -> String {
        let start = self.index(self.startIndex, offsetBy: range.lowerBound)
        let end = self.index(self.startIndex, offsetBy: range.upperBound)
        let subString = self[start..<end]
        return String(subString)
    }

}
gebirgsbärbel
fuente
Su código se bloqueará si range.upperBound es> longitud de la cadena. Además, un uso de muestra también habría sido útil, ya que no estaba familiarizado con los subíndices en Swift. Puede incluir algo como datePartOnly = "2018-01-04-08: 00" [NSMakeRange (0, 10)]. Aparte de eso, muy buena respuesta, +1 :).
dcp
hoy en día es esta cosa extraña: text[Range( nsRange , in: text)!]
Fattie
10

Aquí hay una función que devuelve la subcadena de una subcadena determinada cuando se proporcionan índices de inicio y fin. Para una referencia completa, puede visitar los enlaces que figuran a continuación.

func substring(string: String, fromIndex: Int, toIndex: Int) -> String? {
    if fromIndex < toIndex && toIndex < string.count /*use string.characters.count for swift3*/{
        let startIndex = string.index(string.startIndex, offsetBy: fromIndex)
        let endIndex = string.index(string.startIndex, offsetBy: toIndex)
        return String(string[startIndex..<endIndex])
    }else{
        return nil
    }
}

Aquí hay un enlace a la publicación del blog que he creado para tratar la manipulación de cadenas de forma rápida. Manipulación de cadenas en swift (cubre swift 4 también)

O puedes ver esta esencia en github

Nikesh Jha
fuente
9

Tuve la misma reacción inicial. Yo también estaba frustrado por cómo la sintaxis y los objetos cambian tan drásticamente en cada lanzamiento importante.

Sin embargo, me di cuenta por experiencia de que siempre sufro las consecuencias de tratar de luchar contra el "cambio", como tratar con personajes de varios bytes, lo cual es inevitable si estás mirando a una audiencia global.

Así que decidí reconocer y respetar los esfuerzos realizados por los ingenieros de Apple y hacer mi parte al comprender su mentalidad cuando se les ocurrió este enfoque "horrible".

En lugar de crear extensiones, que es solo una solución alternativa para hacerte la vida más fácil (no estoy diciendo que sean incorrectas o caras), ¿por qué no descubrir cómo están diseñadas ahora las cadenas para funcionar?

Por ejemplo, tenía este código que funcionaba en Swift 2.2:

let rString = cString.substringToIndex(2)
let gString = (cString.substringFromIndex(2) as NSString).substringToIndex(2)
let bString = (cString.substringFromIndex(4) as NSString).substringToIndex(2)

y después de dejar de intentar que el mismo enfoque funcionara, por ejemplo, usando Substrings, finalmente entendí el concepto de tratar Strings como una colección bidireccional para la cual terminé con esta versión del mismo código:

let rString = String(cString.characters.prefix(2))
cString = String(cString.characters.dropFirst(2))
let gString = String(cString.characters.prefix(2))
cString = String(cString.characters.dropFirst(2))
let bString = String(cString.characters.prefix(2))

Espero que esto contribuya ...

Rio Bautista
fuente
1
Bueno, lidiar con un problema complejo no significa que la solución pueda ser elegante. Nuevamente, también entiendo el problema, pero toda la clase String y tratar con él es simplemente horrible.
inexcitus
5

La misma frustración, esto no debería ser tan difícil ...

Compilé este ejemplo de cómo obtener posiciones para la (s) subcadena (s) de un texto más grande:

//
// Play with finding substrings returning an array of the non-unique words and positions in text
//
//

import UIKit

let Bigstring = "Why is it so hard to find substrings in Swift3"
let searchStrs : Array<String>? = ["Why", "substrings", "Swift3"]

FindSubString(inputStr: Bigstring, subStrings: searchStrs)


func FindSubString(inputStr : String, subStrings: Array<String>?) ->    Array<(String, Int, Int)> {
    var resultArray : Array<(String, Int, Int)> = []
    for i: Int in 0...(subStrings?.count)!-1 {
        if inputStr.contains((subStrings?[i])!) {
            let range: Range<String.Index> = inputStr.range(of: subStrings![i])!
            let lPos = inputStr.distance(from: inputStr.startIndex, to: range.lowerBound)
            let uPos = inputStr.distance(from: inputStr.startIndex, to: range.upperBound)
            let element = ((subStrings?[i])! as String, lPos, uPos)
            resultArray.append(element)
        }
    }
    for words in resultArray {
        print(words)
    }
    return resultArray
}

devuelve ("Why", 0, 3) ("subcadenas", 26, 36) ("Swift3", 40, 46)

Danés alto
fuente
3
Es un código, pero en realidad no explica cómo funcionan la indexación de cadenas y las subcadenas en swift3.
Robert
5

Soy nuevo en Swift 3, pero mirando la Stringsintaxis (index) para analogía, creo que ese índice es como un "puntero" restringido a una cadena e Int puede ayudar como un objeto independiente. Usando la sintaxis de base + offset, entonces podemos obtener el i-ésimo carácter de la cadena con el siguiente código:

let s = "abcdefghi"
let i = 2
print (s[s.index(s.startIndex, offsetBy:i)])
// print c

Para un rango de caracteres (índices) de una cadena que usa la sintaxis de String (rango), podemos obtener de i-th a f-th caracteres con el siguiente código:

let f = 6
print (s[s.index(s.startIndex, offsetBy:i )..<s.index(s.startIndex, offsetBy:f+1 )])
//print cdefg

Para una subcadena (rango) de una cadena que usa String.substring (rango) podemos obtener la subcadena usando el siguiente código:

print (s.substring (with:s.index(s.startIndex, offsetBy:i )..<s.index(s.startIndex, offsetBy:f+1 ) ) )
//print cdefg

Notas:

  1. La i-ésima y la f-ésima comienzan con 0.

  2. Para f-th, uso offsetBY: f + 1, porque el rango de uso de suscripción .. <(operador medio abierto), no incluye la posición f-th.

  3. Por supuesto, debe incluir errores de validación como índice no válido.

Nelson Mizutani
fuente
5

Swift 4+

extension String {
    func take(_ n: Int) -> String {
        guard n >= 0 else {
            fatalError("n should never negative")
        }
        let index = self.index(self.startIndex, offsetBy: min(n, self.count))
        return String(self[..<index])
    }
}

Devuelve una subsecuencia de los primeros n caracteres, o la cadena completa si la cadena es más corta. (inspirado en: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/take.html )

Ejemplo:

let text = "Hello, World!"
let substring = text.take(5) //Hello
Peter Kreinz
fuente
4

Soy un pensamiento bastante mecánico. Aquí están los conceptos básicos ...

Swift 4 Swift 5

  let t = "abracadabra"

  let start1 = t.index(t.startIndex, offsetBy:0)
  let   end1 = t.index(t.endIndex, offsetBy:-5)
  let start2 = t.index(t.endIndex, offsetBy:-5)
  let   end2 = t.index(t.endIndex, offsetBy:0)

  let t2 = t[start1 ..< end1]
  let t3 = t[start2 ..< end2]                

  //or a shorter form 

  let t4 = t[..<end1]
  let t5 = t[start2...]

  print("\(t2) \(t3) \(t)")
  print("\(t4) \(t5) \(t)")

  // result:
  // abraca dabra abracadabra

El resultado es una subcadena, lo que significa que es parte de la cadena original. Para obtener una cadena separada completa, solo use eg

    String(t3)
    String(t4)

Esto es lo que uso:

    let mid = t.index(t.endIndex, offsetBy:-5)
    let firstHalf = t[..<mid]
    let secondHalf = t[mid...]
t1ser
fuente
3

Swift 4

extension String {
    subscript(_ i: Int) -> String {
        let idx1 = index(startIndex, offsetBy: i)
        let idx2 = index(idx1, offsetBy: 1)
        return String(self[idx1..<idx2])
    }
}

let s = "hello"

s[0]    // h
s[1]    // e
s[2]    // l
s[3]    // l
s[4]    // o
FlowUI. SimpleUITesting.com
fuente
2

Creé una extensión simple para esto (Swift 3)

extension String {
    func substring(location: Int, length: Int) -> String? {
        guard characters.count >= location + length else { return nil }
        let start = index(startIndex, offsetBy: location)
        let end = index(startIndex, offsetBy: location + length)
        return substring(with: start..<end)
    }
}
Lucas Algarra
fuente
2

Aquí hay una implementación más genérica:

Esta técnica todavía se usa indexpara mantener los estándares de Swift e implica un personaje completo.

extension String
{
    func subString <R> (_ range: R) -> String? where R : RangeExpression, String.Index == R.Bound
    {
        return String(self[range])
    }

    func index(at: Int) -> Index
    {
        return self.index(self.startIndex, offsetBy: at)
    }
}

Para subcadenas del tercer carácter:

let item = "Fred looks funny"
item.subString(item.index(at: 2)...) // "ed looks funny"

He usado camello subStringpara indicar que devuelve ay Stringno a Substring.

Leslie Godwin
fuente
2

Sobre la base de lo anterior, necesitaba dividir una cadena en un carácter que no se imprime y se deja caer el carácter que no se imprime. Desarrollé dos métodos:

var str = "abc\u{1A}12345sdf"
let range1: Range<String.Index> = str.range(of: "\u{1A}")!
let index1: Int = str.distance(from: str.startIndex, to: range1.lowerBound)
let start = str.index(str.startIndex, offsetBy: index1)
let end = str.index(str.endIndex, offsetBy: -0)
let result = str[start..<end] // The result is of type Substring
let firstStr = str[str.startIndex..<range1.lowerBound]

que reuní usando algunas de las respuestas anteriores.

Debido a que una cadena es una colección, hice lo siguiente:

var fString = String()
for (n,c) in str.enumerated(){

*if c == "\u{1A}" {
    print(fString);
    let lString = str.dropFirst(n + 1)
    print(lString)
    break
   }
 fString += String(c)
}*

Lo que para mí fue más intuitivo. ¿Cuál es el mejor? No tengo forma de decir que ambos trabajan con Swift 5

Jeremy Andrews
fuente
Gracias por tu respuesta. ¿Hay algo diferente sobre Strings en Swift 5? Todavía no he tenido tiempo de jugar con eso.
Suragch
Lo dicen pero no he tenido la oportunidad de investigarlo.
Jeremy Andrews
1

Swift 4

"Subcadena" ( https://developer.apple.com/documentation/swift/substring ):

let greeting = "Hi there! It's nice to meet you! 👋"
let endOfSentence = greeting.index(of: "!")!
let firstSentence = greeting[...endOfSentence]
// firstSentence == "Hi there!"

Ejemplo de cadena de extensión:

private typealias HowDoYouLikeThatElonMusk = String
private extension HowDoYouLikeThatElonMusk {

    subscript(_ from: Character?, _ to: Character?, _ include: Bool) -> String? {
        if let _from: Character = from, let _to: Character = to {
            let dynamicSourceForEnd: String = (_from == _to ? String(self.reversed()) : self)
            guard let startOfSentence: String.Index = self.index(of: _from),
                let endOfSentence: String.Index = dynamicSourceForEnd.index(of: _to) else {
                return nil
            }

            let result: String = String(self[startOfSentence...endOfSentence])
            if include == false {
                guard result.count > 2 else {
                        return nil
                }
                return String(result[result.index(result.startIndex, offsetBy: 1)..<result.index(result.endIndex, offsetBy: -1)])
            }
            return result
        } else if let _from: Character = from {
            guard let startOfSentence: String.Index = self.index(of: _from) else {
                return nil
            }
            let result: String = String(self[startOfSentence...])
            if include == false {
                guard result.count > 1 else {
                    return nil
                }
                return String(result[result.index(result.startIndex, offsetBy: 1)...])
            }
            return result
        } else if let _to: Character = to {
            guard let endOfSentence: String.Index = self.index(of: _to) else {
                    return nil
            }
            let result: String = String(self[...endOfSentence])
            if include == false {
                guard result.count > 1 else {
                    return nil
                }
                return String(result[..<result.index(result.endIndex, offsetBy: -1)])
            }
            return result
        }
        return nil
    }
}

ejemplo de uso de la cadena de extensión:

let source =                                   ">>>01234..56789<<<"
// include = true
var from =          source["3", nil, true]  //       "34..56789<<<"
var to =            source[nil, "6", true]  // ">>>01234..56"
var fromTo =        source["3", "6", true]  //       "34..56"
let notFound =      source["a", nil, true]  // nil
// include = false
from =              source["3", nil, false] //        "4..56789<<<"
to =                source[nil, "6", false] // ">>>01234..5"
fromTo =            source["3", "6", false] //        "4..5"
let outOfBounds =   source[".", ".", false] // nil

let str = "Hello, playground"
let hello = str[nil, ",", false] // "Hello"
CAHbl463
fuente
-1

Swift 5
let desiredIndex: Int = 7 let substring = str[String.Index(encodedOffset: desiredIndex)...]
Esta variable de subcadena le dará el resultado.
Simplemente aquí Int se convierte en Índice y luego puede dividir las cadenas. A menos que obtenga errores.

Wimukthi Rajapaksha
fuente
2
Esto está mal. Un personaje puede constar de uno o más bytes. Solo funciona con texto ascii.
Leo Dabus