¿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?


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í .


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

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

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"

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))

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]

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

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

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"

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

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

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.


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

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

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

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)

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(","))

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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.