Subcadena de una cadena en swift | Índice de una subcadena en una cadena

Estoy acostumbrado a hacer esto en JavaScript:

var domains = "abcde".substring(0, "abcde".indexOf("cd")) // Returns "ab" 

Swift no tiene esta función, ¿cómo hacer algo similar?

Xcode 9.x • Swift 4.x

 extension StringProtocol where Index == String.Index { func index(of string: T, options: String.CompareOptions = []) -> Index? { return range(of: string, options: options)?.lowerBound } func endIndex(of string: T, options: String.CompareOptions = []) -> Index? { return range(of: string, options: options)?.upperBound } func indexes(of string: T, options: String.CompareOptions = []) -> [Index] { var result: [Index] = [] var start = startIndex while start < endIndex, let range = range(of: string, options: options, range: start..(of string: T, options: String.CompareOptions = []) -> [Range] { var result: [Range] = [] var start = startIndex while start < endIndex, let range = range(of: string, options: options, range: start.. 

uso:

 let str = "abcde" if let index = str.index(of: "cd") { let domains = str.prefix(upTo: index) print(domains) // "ab\n" } 

 let str = "Hello, playground, playground, playground" str.index(of: "play") // 7 str.endIndex(of: "play") // 11 str.indexes(of: "play") // [7, 19, 31] str.ranges(of: "play") // [{lowerBound 7, upperBound 11}, {lowerBound 19, upperBound 23}, {lowerBound 31, upperBound 35}] 

Probado para Swift 4.1 / 4.0 / 3.0

Utilizando el subíndice String[Range] puede obtener la cadena secundaria. Necesita iniciar índice y último índice para crear el rango y puede hacerlo de la siguiente manera

 let str = "abcde" if let range = str.range(of: "cd") { let substring = str[.. 

Si no define el índice de inicio, este operador ..< toma el índice inicial. También puede usar str[str.startIndex.. lugar de str[..

En Swift 4:

Obtener el índice de un personaje en una cadena:

 let str = "abcdefghabcd" if let index = str.index(of: "b") { print(index) // Index(_compoundOffset: 4, _cache: Swift.String.Index._Cache.character(1)) } 

Crear SubString (prefijo y sufijo) de String usando Swift 4:

 let str : String = "ilike" for i in 0...str.count { let index = str.index(str.startIndex, offsetBy: i) // String.Index let prefix = str[.. 

Salida

 prefix , suffix : ilike prefix i, suffix : like prefix il, suffix : ike prefix ili, suffix : ke prefix ilik, suffix : e prefix ilike, suffix : 

Si desea generar una subcadena entre 2 índices, use:

 let substring1 = string[startIndex...endIndex] // including endIndex let subString2 = string[startIndex.. 

Hacer esto en Swift es posible, pero se necesitan más líneas, aquí está una función indexOf() haciendo lo que se espera:

 func indexOf(source: String, substring: String) -> Int? { let maxIndex = source.characters.count - substring.characters.count for index in 0...maxIndex { let rangeSubstring = source.startIndex.advancedBy(index).. 

Esta función no está optimizada, pero hace el trabajo para cadenas cortas.

En la versión 3 de Swift, String no tiene funciones como –

 str.index(of: String) 

Si se requiere el índice para una subcadena, una de las formas es obtener el rango. Tenemos las siguientes funciones en la cadena que devuelve rango –

 str.range(of: ) str.rangeOfCharacter(from: ) str.range(of: , options: , range: ?>, locale: ) 

Por ejemplo, para encontrar los índices de la primera aparición de juego en str

 var str = "play play play" var range = str.range(of: "play") range?.lowerBound //Result : 0 range?.upperBound //Result : 4 

Nota: el rango es opcional. Si no puede encontrar la Cadena, la hará nula. Por ejemplo

 var str = "play play play" var range = str.range(of: "zoo") //Result : nil range?.lowerBound //Result : nil range?.upperBound //Result : nil 

Hay tres problemas estrechamente relacionados aquí:

  • Todos los métodos de búsqueda de subcadenas han terminado en el mundo Cocoa NSString (Fundación)

  • Foundation NSRange tiene un desajuste con Swift Range; el primero usa inicio y longitud, este último usa puntos finales

  • En general, los caracteres de Swift se indexan usando String.Index , no Int, pero los caracteres de Foundation se indexan usando Int, y no hay una traducción directa simple entre ellos (porque Foundation y Swift tienen diferentes ideas de lo que constituye un personaje)

Teniendo en cuenta todo eso, pensemos en cómo escribir:

 func substring(of s: String, from:Int, toSubstring s2 : String) -> Substring? { // ? } 

La subcadena s2 debe buscar en s utilizando un método de String Foundation. El rango resultante vuelve a nosotros, no como un NSRange (aunque este es un método de Foundation), sino como un Range of String.Index ( String.Index en un Optional, en caso de que no encontremos la subcadena). Sin embargo, el otro número, from , es un Int. Por lo tanto, no podemos formar ningún tipo de rango que los involucre a ambos.

¡Pero no tenemos que hacerlo! Todo lo que tenemos que hacer es cortar el final de nuestra cadena original usando un método que toma un String.Index , y cortar el inicio de nuestra cadena original usando un método que toma un Int. ¡Afortunadamente, tales métodos existen! Me gusta esto:

 func substring(of s: String, from:Int, toSubstring s2 : String) -> Substring? { guard let r = s.range(of:s2) else {return nil} var s = s.prefix(upTo:r.lowerBound) s = s.dropFirst(from) return s } 

O, si prefiere poder aplicar este método directamente a una cadena, como esta …

 let output = "abcde".substring(from:0, toSubstring:"cd") 

… luego haz una extensión en String:

 extension String { func substring(from:Int, toSubstring s2 : String) -> Substring? { guard let r = self.range(of:s2) else {return nil} var s = self.prefix(upTo:r.lowerBound) s = s.dropFirst(from) return s } }