Substring de uma string em swift | Índice de uma substring em uma string

Eu estou acostumado a fazer isso em JavaScript:

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

O Swift não tem essa function, como fazer algo parecido?

    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}] 

    Testado para o Swift 4.1 / 4.0 / 3.0

    Usando String[Range] subscrito você pode obter a sub-string. Você precisa iniciar o índice e o último índice para criar o intervalo e você pode fazê-lo como abaixo

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

    Se você não definir o índice inicial deste operador ..< , ele pega o índice inicial. Você também pode usar str[str.startIndex.. vez de str[..

    No Swift 4:

    Obtendo o índice de um caractere em uma string:

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

    Criando SubString (prefixo e sufixo) de String usando o 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[.. 

    Saída

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

    Se você quiser gerar uma substring entre dois índices, use:

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

    Fazer isso no Swift é possível, mas é preciso mais linhas, aqui está uma function indexOf() fazendo o que é esperado:

     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 function não é otimizada, mas faz o trabalho para strings curtas.

    Na versão 3 do Swift, String não tem funções como –

     str.index(of: String) 

    Se o índice for necessário para uma substring, uma das maneiras é obter o intervalo. Nós temos as seguintes funções na string que retorna range –

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

    Por exemplo, para encontrar os índices da primeira ocorrência de jogo em str

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

    Nota: o intervalo é opcional. Se não for capaz de encontrar a String, ela será nula. Por exemplo

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

    Há três problemas intimamente conectados aqui:

    • Todos os methods de localização de substring terminaram no mundo do NSString de cocoa (Foundation)

    • O Foundation NSRange tem uma incompatibilidade com o Swift Range; o primeiro usa início e comprimento, o último usa terminais

    • Em geral, os caracteres Swift são indexados usando String.Index , não Int, mas os caracteres Foundation são indexados usando Int, e não há tradução direta simples entre eles (porque Foundation e Swift têm idéias diferentes do que constitui um caractere)

    Dado tudo isso, vamos pensar em como escrever:

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

    A substring s2 deve ser procurada em s usando um método String Foundation. O intervalo resultante retorna para nós, não como um NSRange (embora este seja um método Foundation), mas como um Range of String.Index (empacotado em um opcional, caso não tenhamos encontrado a substring). No entanto, o outro número, from , é um Int. Assim, não podemos formar qualquer tipo de alcance envolvendo os dois.

    Mas nós não precisamos! Tudo o que precisamos fazer é cortar o final da string original usando um método que use String.Index e cortar o início da string original usando um método que use Int. Felizmente, esses methods existem! Como isso:

     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 } 

    Ou, se preferir poder aplicar este método diretamente a uma string, como esta …

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

    … então faça uma extensão em 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 } }