¿Cómo puedo usar los subíndices de segmentación de cadenas en Swift 4?

294

Tengo el siguiente código simple escrito en Swift 3:

let str = "Hello, playground"
let index = str.index(of: ",")!
let newStr = str.substring(to: index)

De Xcode 9 beta 5, recibo la siguiente advertencia:

' substring(to:)' está en desuso: utilice el Stringsubíndice de corte con un operador 'rango parcial desde'.

¿Cómo se puede utilizar este subíndice de corte con rango parcial en Swift 4?

Adrian
fuente
var str = "Hola, patio de juegos" let indexcut = str.firstIndex (of: ",") print (String (str [.. <indexcut!])) print (String (str [indexcut! ...]))
usuario1828845

Respuestas:

375

Debe dejar un lado vacío , de ahí el nombre de "rango parcial".

let newStr = str[..<index]

Lo mismo significa rango parcial de operadores, solo deje el otro lado vacío:

let newStr = str[index...]

Tenga en cuenta que estos operadores de rango devuelven a Substring. Si desea convertirlo en una cadena, use Stringla función de inicialización:

let newStr = String(str[..<index])

Puede leer más sobre las nuevas subcadenas aquí .

Tamás Sengel
fuente
8
str[..<index]devuelve a Substring. Si quieres newStrser un Stringtienes que escribir:let newStr = "\(str[..<index])"
Lindemann
12
El uso de la interpolación de cadenas con un solitario Substringes probablemente un poco confuso, ya que lo que realmente está tratando de lograr es Stringla inicialización: let newStr = String(str[..<index]).
Gary
55
Actualización del código donde mi valor 'índice' era simplemente un entero produce un mensaje de error, Cannot subscript a value of type 'String' with an index of type 'PartialRangeUpTo<Int>'. ¿Qué tipos de valores deben usarse allí?
ConfusionTowers
22
@ConfusionTowers, los índices de cadena Swift no son enteros , y eso no ha cambiado con la versión 4. Probablemente necesitará str[..<str.index(str.startIndex, offsetBy: 8)]o algo así. Tenga en cuenta que str.indexes una operación de tiempo lineal en función de offsetBy.
zneak
66
@zneak Probablemente quierasstr.prefix(8)
Tim Vermeulen
264

Convertir subcadena (Swift 3) en segmentación de cadenas (Swift 4)

Ejemplos en Swift 3, 4:

let newStr = str.substring(to: index) // Swift 3
let newStr = String(str[..<index]) // Swift 4

let newStr = str.substring(from: index) // Swift 3
let newStr = String(str[index...]) // Swift 4 

let range = firstIndex..<secondIndex // If you have a range
let newStr = = str.substring(with: range) // Swift 3
let newStr = String(str[range])  // Swift 4
Mohammad Sadegh Panadgoo
fuente
55
Perfecto, y gracias por dar los 3 y 4 ejemplos uno al lado del otro, hace que actualizar mi proyecto sea mucho más fácil.
Ethan Parker
86

Swift 5, 4

Uso

let text = "Hello world"
text[0] // H
text[...3] // "Hell"
text[6..<text.count] // world
text[NSRange(location: 6, length: 3)] // wor

Código

import Foundation

public extension String {
  subscript(value: Int) -> Character {
    self[index(at: value)]
  }
}

public extension String {
  subscript(value: NSRange) -> Substring {
    self[value.lowerBound..<value.upperBound]
  }
}

public extension String {
  subscript(value: CountableClosedRange<Int>) -> Substring {
    self[index(at: value.lowerBound)...index(at: value.upperBound)]
  }

  subscript(value: CountableRange<Int>) -> Substring {
    self[index(at: value.lowerBound)..<index(at: value.upperBound)]
  }

  subscript(value: PartialRangeUpTo<Int>) -> Substring {
    self[..<index(at: value.upperBound)]
  }

  subscript(value: PartialRangeThrough<Int>) -> Substring {
    self[...index(at: value.upperBound)]
  }

  subscript(value: PartialRangeFrom<Int>) -> Substring {
    self[index(at: value.lowerBound)...]
  }
}

private extension String {
  func index(at offset: Int) -> String.Index {
    index(startIndex, offsetBy: offset)
  }
}
dimpiax
fuente
14
Esta funcionalidad debería ser un comportamiento rápido predeterminado.
Laimis
44
Definitivamente PR esto en Swift lib: D
OhadM
2
Esta es una solución de la parte más fea de Swift.
Dmitry
@Dmitry a alguien no le gustó, ya que esta respuesta tiene -2. : D
dimpiax
Esta es una mala respuesta ya que el operador de subíndice oculta la complejidad O (n) de la función de índice. Una buena API de programación solo usa subíndice para denotar una búsqueda rápida.
Ragnarius
38

Más corto en Swift 4/5:

var string = "123456"
string = String(string.prefix(3)) //"123"
string = String(string.suffix(3)) //"456"
ilnur
fuente
26

La conversión de su código a Swift 4 también se puede hacer de esta manera:

let str = "Hello, playground"
let index = str.index(of: ",")!
let substr = str.prefix(upTo: index)

Puede usar el siguiente código para tener una nueva cadena:

let newString = String(str.prefix(upTo: index))
Thyerri Mezzari
fuente
17

subcadena (de: índice) Convertido a [índice ...]

Revise la muestra

let text = "1234567890"
let index = text.index(text.startIndex, offsetBy: 3)

text.substring(from: index) // "4567890"   [Swift 3]
String(text[index...])      // "4567890"   [Swift 4]
Guarida
fuente
1
los caracteres están en desuso en Swift 4, creo que hay que cambiar el ejemplo para obtener el índice de Swift 4
AbuTaareq
Esto me ayudo. tnx
usuario1105951
17

Swift5

(Método de subcadena de Java):

extension String {
    func subString(from: Int, to: Int) -> String {
       let startIndex = self.index(self.startIndex, offsetBy: from)
       let endIndex = self.index(self.startIndex, offsetBy: to)
       return String(self[startIndex...endIndex])
    }
}

Uso:

var str = "Hello, Nick Michaels"
print(str.subString(from:7,to:20))
// print Nick Michaels
August Lin
fuente
2
Todavía funciona en Swift 5. Estaba buscando una subcadena de estilo Java ( frompor to-1ejemplo, "Hello".substring(1,4)devuelve "ell"). Con una pequeña modificación ( startIndex..<endIndex), esta es la mejor solución que he encontrado hasta ahora que hace exactamente eso con solo unas pocas líneas de código.
Neph
9

Algunas extensiones útiles:

extension String {
    func substring(from: Int, to: Int) -> String {
        let start = index(startIndex, offsetBy: from)
        let end = index(start, offsetBy: to - from)
        return String(self[start ..< end])
    }

    func substring(range: NSRange) -> String {
        return substring(from: range.lowerBound, to: range.upperBound)
    }
}
Johannes
fuente
Interesante, estaba pensando lo mismo. ¿Es la cadena (línea ["http: //" .endIndex ...]) más clara que la subcadena en desuso? line.substring (de: "http: //" .endIndex) tal vez hasta que alcancen el objetivo declarado de un sorprendente manejo de cadenas, no deben desaprobar la subcadena.
Posible
7

Ejemplo de uppercasedFirstCharacterpropiedad de conveniencia en Swift3 y Swift4.

La propiedad uppercasedFirstCharacterNewmuestra cómo usar el subíndice de corte de cadenas en Swift4.

extension String {

   public var uppercasedFirstCharacterOld: String {
      if characters.count > 0 {
         let splitIndex = index(after: startIndex)
         let firstCharacter = substring(to: splitIndex).uppercased()
         let sentence = substring(from: splitIndex)
         return firstCharacter + sentence
      } else {
         return self
      }
   }

   public var uppercasedFirstCharacterNew: String {
      if characters.count > 0 {
         let splitIndex = index(after: startIndex)
         let firstCharacter = self[..<splitIndex].uppercased()
         let sentence = self[splitIndex...]
         return firstCharacter + sentence
      } else {
         return self
      }
   }
}

let lorem = "lorem".uppercasedFirstCharacterOld
print(lorem) // Prints "Lorem"

let ipsum = "ipsum".uppercasedFirstCharacterNew
print(ipsum) // Prints "Ipsum"
Vlad
fuente
1
Si te refieres a la subcadena (con: rango) -> self [rango]
Arsen Vartbaronov
6

Puede crear su método de subcadena personalizado usando la extensión a la clase Cadena de la siguiente manera:

extension String {
    func subString(startIndex: Int, endIndex: Int) -> String {
        let end = (endIndex - self.count) + 1
        let indexStartOfText = self.index(self.startIndex, offsetBy: startIndex)
        let indexEndOfText = self.index(self.endIndex, offsetBy: end)
        let substring = self[indexStartOfText..<indexEndOfText]
        return String(substring)
    }
}
Chhaileng
fuente
Si esto va a incluir un endIndex, también debe ser capaz de manejar fuera de los límites.
Jay
5

Crear SubString (prefijo y sufijo) a partir 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[..<index] // String.SubSequence
    let suffix = str[index...] // String.SubSequence
    print("prefix \(prefix), suffix : \(suffix)")
}

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..<endIndex] // excluding endIndex
Ashis Laha
fuente
let prefix = str [... <índice>] en lugar de str [.. <índice>] falta un solo punto.
AbuTaareq
@AbuTaareq, ¿de cuál estás hablando? let prefix = str [.. <index], es perfecto. (cadena de prefijo). Intenta en el campo de juego para tener más contexto.
Ashis Laha
4

He escrito una extensión de cadena para reemplazar 'String: subString:'

extension String {
    
    func sliceByCharacter(from: Character, to: Character) -> String? {
        let fromIndex = self.index(self.index(of: from)!, offsetBy: 1)
        let toIndex = self.index(self.index(of: to)!, offsetBy: -1)
        return String(self[fromIndex...toIndex])
    }
    
    func sliceByString(from:String, to:String) -> String? {
        //From - startIndex
        var range = self.range(of: from)
        let subString = String(self[range!.upperBound...])
        
        //To - endIndex
        range = subString.range(of: to)
        return String(subString[..<range!.lowerBound])
    }
    
}

Uso: "Date(1511508780012+0530)".sliceByString(from: "(", to: "+")

Resultado del ejemplo : "1511508780012"

PD: los opcionales se ven obligados a desenvolverse. Agregue tipo de verificación de seguridad cuando sea necesario.

porJeevan
fuente
Precaución: los opcionales se ven obligados a desenvolverse. agregue tipo de verificación de seguridad si es necesario.
porJeevan
3

Cuando programo, a menudo tengo cadenas con simplemente A-Za-z y 0-9. No es necesario realizar acciones difíciles del índice. Esta extensión se basa en las antiguas funciones simples izquierda / media / derecha.

extension String {

    // LEFT
    // Returns the specified number of chars from the left of the string
    // let str = "Hello"
    // print(str.left(3))         // Hel
    func left(_ to: Int) -> String {
        return "\(self[..<self.index(startIndex, offsetBy: to)])"
    }

    // RIGHT
    // Returns the specified number of chars from the right of the string
    // let str = "Hello"
    // print(str.left(3))         // llo
    func right(_ from: Int) -> String {
        return "\(self[self.index(startIndex, offsetBy: self.length-from)...])"
    }

    // MID
    // Returns the specified number of chars from the startpoint of the string
    // let str = "Hello"
    // print(str.left(2,amount: 2))         // ll
    func mid(_ from: Int, amount: Int) -> String {
        let x = "\(self[self.index(startIndex, offsetBy: from)...])"
        return x.left(amount)
    }
}
Vincent
fuente
¡¡Gran idea!! Sin embargo, es triste que sea necesario abstraer las características de Swift solo porque cambian constantemente la forma en que funcionan las cosas. Supongo que quieren que todos nos enfoquemos en construcciones en lugar de productividad. De todos modos, hice algunas actualizaciones menores a su código fino: pastebin.com/ManWmNnW
Fredrik Johansson
2

con este método puede obtener un rango específico de cadena. Debe pasar el índice de inicio y después de ese número total de caracteres que desea.

extension String{
    func substring(fromIndex : Int,count : Int) -> String{
        let startIndex = self.index(self.startIndex, offsetBy: fromIndex)
        let endIndex = self.index(self.startIndex, offsetBy: fromIndex + count)
        let range = startIndex..<endIndex
        return String(self[range])
    }
}
jayesh kanzariya
fuente
2

Esta es mi solución, sin advertencia, sin errores, pero perfecta.

let redStr: String = String(trimmStr[String.Index.init(encodedOffset: 0)..<String.Index.init(encodedOffset: 2)])
let greenStr: String = String(trimmStr[String.Index.init(encodedOffset: 3)..<String.Index.init(encodedOffset: 4)])
let blueStr: String = String(trimmStr[String.Index.init(encodedOffset: 5)..<String.Index.init(encodedOffset: 6)])
Victor John
fuente
El uso de encodedOffsetse considera perjudicial y quedará en desuso .
Martin R
1

Espero que esto ayude un poco más: -

var string = "123456789"

Si desea una subcadena después de algún índice en particular.

var indexStart  =  string.index(after: string.startIndex )// you can use any index in place of startIndex
var strIndexStart   = String (string[indexStart...])//23456789

Si desea una subcadena después de eliminar alguna cadena al final.

var indexEnd  =  string.index(before: string.endIndex)
var strIndexEnd   = String (string[..<indexEnd])//12345678

También puede crear índices con el siguiente código: -

var  indexWithOffset =  string.index(string.startIndex, offsetBy: 4)
Anurag Bhakuni
fuente
0

Espero que sea útil.

extension String {
    func getSubString(_ char: Character) -> String {
        var subString = ""
        for eachChar in self {
            if eachChar == char {
                return subString
            } else {
                subString += String(eachChar)
            }
        }
        return subString
    }
}


let str: String = "Hello, playground"
print(str.getSubString(","))
Anand Verma
fuente
0
var str = "Hello, playground"
let indexcut = str.firstIndex(of: ",")
print(String(str[..<indexcut!]))
print(String(str[indexcut!...]))

Puede intentarlo de esta manera y obtendrá los resultados adecuados.

usuario1828845
fuente