Come posso usare gli script di slicing delle stringhe in Swift 4?


294

Ho il seguente semplice codice scritto in Swift 3:

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

Da Xcode 9 beta 5, ricevo il seguente avviso:

' substring(to:)' è obsoleto: si prega di utilizzare il Stringcomando di suddivisione in sezioni con un operatore 'intervallo parziale da'.

In che modo questo peduncolo di suddivisione con intervallo parziale può essere utilizzato in Swift 4?


var str = "Ciao, parco giochi" let indexcut = str.firstIndex (of: ",") print (String (str [.. <indexcut!])) print (String (str [indexcut! ...]))
user1828845

Risposte:


375

Dovresti lasciare un lato vuoto , da cui il nome "intervallo parziale".

let newStr = str[..<index]

Lo stesso significa distanza parziale dagli operatori, lascia vuoto l'altro lato:

let newStr = str[index...]

Tieni presente che questi operatori di gamma restituiscono a Substring. Se vuoi convertirlo in una stringa, usa Stringla funzione di inizializzazione:

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

Puoi leggere di più sulle nuove sottostringhe qui .


8
str[..<index]restituisce a Substring. Se vuoi newStressere un Stringdevi scrivere:let newStr = "\(str[..<index])"
Lindemann il

12
Utilizzando stringa di interpolazione con un solitario Substringè probabilmente un po 'di confusione, dal momento che ciò che si sta realmente cercando di realizzare è Stringl'inizializzazione: let newStr = String(str[..<index]).
Gary,

5
Aggiornamento del codice in cui il mio valore 'indice' stato semplicemente un intero restituisce un messaggio di errore, Cannot subscript a value of type 'String' with an index of type 'PartialRangeUpTo<Int>'. Quali tipi di valori devono essere usati lì?
ConfusionTowers il

22
@ConfusionTowers, gli indici di stringa Swift non sono numeri interi e ciò non è cambiato con la versione 4. Probabilmente avrai bisogno di str[..<str.index(str.startIndex, offsetBy: 8)]qualcosa del genere. Tieni presente che str.indexè un'operazione a tempo lineare in funzione di offsetBy.
zneak,

6
@zneak Probabilmente vuoistr.prefix(8)
Tim Vermeulen,

264

Converti sottostringa (Swift 3) in String Slicing (Swift 4)

Esempi in 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

5
Perfecto, e grazie per aver dato i 3 e 4 esempi fianco a fianco, rende più semplice l'aggiornamento del mio progetto!
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

Codice

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
questa funzionalità dovrebbe essere un comportamento rapido predefinito.
Laimis,

4
Sicuramente PR questo in Swift lib: D
OhadM

2
Questa è una correzione della parte più brutta di Swift.
Dmitry,

@Dmitry a qualcuno non è piaciuto, poiché questa risposta ha -2. : D
dimpiax,

Questa è una cattiva risposta poiché l'operatore del pedice nasconde la complessità O (n) della funzione indice. Una buona API di programmazione utilizza solo il pedice per indicare la ricerca rapida.
Ragnarius,

38

Più breve in Swift 4/5:

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

26

La conversione del tuo codice in Swift 4 può anche essere fatta in questo modo:

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

Puoi usare il codice qui sotto per avere una nuova stringa:

let newString = String(str.prefix(upTo: index))

17

sottostringa (da: indice) Convertito in [indice ...]

Controlla il campione

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
i personaggi sono deprecati in Swift 4, penso che devi cambiare l'esempio per ottenere l'indice per Swift 4
AbuTaareq

Questo mi ha aiutato. tnx
user1105951

17

Swift5

(Metodo di sottostringa di 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
Funziona ancora in Swift 5. Stavo cercando una sottostringa in stile Java ( fromad to-1esempio, "Hello".substring(1,4)restituisce "ell"). Con una piccola modifica ( startIndex..<endIndex) questa è la soluzione migliore che ho trovato finora che fa esattamente questo con solo poche righe di codice.
Neph,

9

Alcune estensioni utili:

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

Interessante, stavo pensando lo stesso. String (line ["http: //" .endIndex ...]) è più chiaro della sottostringa obsoleta? line.substring (da: "http: //" .endIndex) forse fino a quando non raggiungono l'obiettivo dichiarato della straordinaria gestione delle stringhe, non dovrebbero deprecare la sottostringa.
possen

7

Esempio di uppercasedFirstCharacter proprietà convenienza in Swift3 e Swift4.

La proprietà uppercasedFirstCharacterNewdimostra come utilizzare il parametro di tipo String slicing in 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
Se vuoi dire sottostringa (con: range) -> self [range]
Arsen Vartbaronov

6

Puoi creare il tuo metodo di sottostringa personalizzato usando l'estensione alla classe String come di seguito:

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

Se questo sta per contenere un endIndex, deve essere in grado di gestire anche i limiti.
Jay,

5

Creazione di sottostringa (prefisso e suffisso) da String utilizzando 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)")
}

Produzione

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

Se si desidera generare una sottostringa tra 2 indici, utilizzare:

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

let prefix = str [... <index>] invece di str [.. <index>] manca un singolo punto.
AbuTaareq

@AbuTaareq, di quale stai parlando? lascia prefisso = str [.. <indice], è perfetto. (stringa prefisso). Prova nel terreno di gioco per ottenere più contesto.
Ashis Laha

4

Ho scritto un'estensione di stringa per la sostituzione di '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])
    }
    
}

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

Risultato di esempio : "1511508780012"

PS: gli opzionali sono costretti a scartare. Aggiungi il controllo di sicurezza del tipo ove necessario.


Attenzione: gli optionals sono costretti a scartare. aggiungere il controllo di sicurezza del tipo, se necessario.
Jeevan il

3

Durante la programmazione ho spesso stringhe con solo A-Za-z e 0-9. Non sono necessarie azioni dell'Indice difficili. Questa estensione si basa sulle semplici vecchie funzioni sinistra / metà / destra.

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

Grande idea!! Purtroppo però è necessario astrarre le funzionalità di Swift solo perché cambiano costantemente il modo in cui funzionano le cose. Immagino che vogliono che tutti noi ci concentriamo sui costrutti anziché sulla produttività. Ad ogni modo, ho apportato alcuni piccoli aggiornamenti al tuo codice: pastebin.com/ManWmNnW
Fredrik Johansson,

2

con questo metodo è possibile ottenere un intervallo specifico di string. È necessario passare l'indice iniziale e dopo il numero totale di caratteri desiderati.

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

Questa è la mia soluzione, nessun avvertimento, nessun errore, ma perfetta

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

L'uso di encodedOffsetè considerato dannoso e sarà deprecato .
Martin R

1

Spero che questo possa aiutare un po 'di più: -

var string = "123456789"

Se si desidera una sottostringa dopo un determinato indice.

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

Se si desidera una sottostringa dopo aver rimosso una stringa alla fine.

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

puoi anche creare indici con il seguente codice: -

var  indexWithOffset =  string.index(string.startIndex, offsetBy: 4)

0

Spero possa essere utile.

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

Puoi provare in questo modo e otterrai risultati corretti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.