Comment puis-je utiliser des indices de découpage de chaîne dans Swift 4?


294

J'ai le code simple suivant écrit dans Swift 3:

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

À partir de Xcode 9 beta 5, je reçois l'avertissement suivant:

' substring(to:)' est obsolète: veuillez utiliser l' Stringindice de découpage avec un opérateur 'plage partielle de'.

Comment cet indice de découpage avec plage partielle peut-il être utilisé dans Swift 4?


var str = "Bonjour, aire de jeux" let indexcut = str.firstIndex (of: ",") print (String (str [.. <indexcut!])) print (String (str [indexcut! ...]))
user1828845

Réponses:


375

Vous devez laisser un côté vide , d'où le nom "plage partielle".

let newStr = str[..<index]

Il en va de même pour la plage partielle des opérateurs, laissez simplement l'autre côté vide:

let newStr = str[index...]

N'oubliez pas que ces opérateurs de plage retournent a Substring. Si vous souhaitez le convertir en chaîne, utilisez Stringla fonction d'initialisation de:

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

Vous pouvez en savoir plus sur les nouvelles sous-chaînes ici .


8
str[..<index]renvoie a Substring. Si vous voulez newStrêtre un, Stringvous devez écrire:let newStr = "\(str[..<index])"
Lindemann

12
En utilisant l' interpolation de chaîne avec un seul Substringest probablement un peu déroutant, car ce que vous essayez d'accomplir vraiment est l' Stringinitialisation: let newStr = String(str[..<index]).
Gary

5
Code mise à jour où ma valeur « index » est simplement un entier donne un message d'erreur, Cannot subscript a value of type 'String' with an index of type 'PartialRangeUpTo<Int>'. Quels types de valeurs faut-il y utiliser?
ConfusionTowers

22
@ConfusionTowers, les indices de chaîne Swift ne sont pas des entiers , et cela n'a pas changé avec la version 4. Vous en aurez probablement besoin str[..<str.index(str.startIndex, offsetBy: 8)]ou quelque chose comme ça. Gardez à l'esprit qu'il str.indexs'agit d'une opération linéaire en fonction de offsetBy.
zneak

6
@zneak Vous voulez probablementstr.prefix(8)
Tim Vermeulen

264

Convertir une sous-chaîne (Swift 3) en un découpage de chaîne (Swift 4)

Exemples dans 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, et merci d'avoir donné les 3 et 4 exemples côte à côte, facilite la mise à jour de mon projet!
Ethan Parker

86

Swift 5, 4

Usage

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

Code

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
cette fonctionnalité doit être un comportement rapide par défaut.
Laimis

4
Certainement PR ceci dans Swift lib: D
OhadM

2
Ceci est un correctif de la partie la plus laide du Swift.
Dmitry

@Dmitry quelqu'un n'a pas aimé, car cette réponse a -2. : D
dimpiax

C'est une mauvaise réponse car l'opérateur d'indice cache la complexité O (n) de la fonction d'index. Une bonne API de programmation utilise uniquement l'indice pour indiquer une recherche rapide.
ragnarius

38

Plus court dans Swift 4/5:

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

26

La conversion de votre code en Swift 4 peut également se faire de cette façon:

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

Vous pouvez utiliser le code ci-dessous pour avoir une nouvelle chaîne:

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

17

substring (from: index) Converti en [index ...]

Vérifiez l'échantillon

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
les caractères sont dépréciés dans Swift 4, je pense que vous devez changer l'exemple pour obtenir l'index pour Swift 4
AbuTaareq

Cela m'a aidé. tnx
user1105951

17

Swift5

(Méthode de sous-chaîne 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])
    }
}

Usage:

var str = "Hello, Nick Michaels"
print(str.subString(from:7,to:20))
// print Nick Michaels

2
Fonctionne toujours dans Swift 5. Je cherchais une sous-chaîne de style Java ( frompar to-1exemple, "Hello".substring(1,4)renvoie "ell"). Avec une petite modification ( startIndex..<endIndex), c'est la meilleure solution que j'ai trouvée jusqu'à présent qui fait exactement cela avec seulement quelques lignes de code.
Neph

9

Quelques extensions utiles:

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

Intéressant, je pensais la même chose. La chaîne (ligne ["http: //" .endIndex ...]) est-elle plus claire que la sous-chaîne déconseillée? line.substring (from: "http: //" .endIndex) peut-être jusqu'à ce qu'ils atteignent l'objectif déclaré de gestion incroyable des chaînes, ils ne devraient pas déprécier la sous-chaîne.
possen

7

Exemple de uppercasedFirstCharacterpropriété de commodité dans Swift3 et Swift4.

La propriété uppercasedFirstCharacterNewmontre comment utiliser l'indice de découpage de chaîne dans 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 vous voulez dire sous-chaîne (avec: plage) -> auto [plage]
Arsen Vartbaronov

6

Vous pouvez créer votre méthode de sous-chaîne personnalisée en utilisant l'extension de la classe String comme ci-dessous:

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 cela va prendre dans un endIndex, il doit également être capable de gérer hors des limites.
Jay

5

Création d'une sous-chaîne (préfixe et suffixe) à partir de String à l'aide de 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)")
}

Production

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

Si vous souhaitez générer une sous-chaîne entre 2 indices, utilisez:

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

laissez prefix = str [... <index>] au lieu de str [.. <index>] un seul point est manquant.
AbuTaareq

@AbuTaareq, de qui parlez-vous? soit prefix = str [.. <index], c'est parfait. (chaîne de préfixe). Essayez sur le terrain de jeu pour obtenir plus de contexte.
Ashis Laha

4

J'ai écrit une extension de chaîne pour remplacer '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])
    }
    
}

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

Exemple de résultat : "1511508780012"

PS: les optionnels sont obligés de déballer. Veuillez ajouter un contrôle de sécurité de type chaque fois que nécessaire.


Attention: les options sont obligées de déballer. veuillez ajouter un contrôle de sécurité de type si nécessaire.
byJeevan

3

Lors de la programmation, j'ai souvent des chaînes avec simplement A-Za-z et 0-9. Pas besoin d'actions d'index difficiles. Cette extension est basée sur les anciennes fonctions simples gauche / milieu / droite.

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

Bonne idée!! Malheureusement, il est nécessaire d'abstraire les fonctionnalités de Swift simplement parce qu'elles changent constamment la façon dont les choses fonctionnent. Je suppose qu'ils veulent que nous nous concentrions tous sur les constructions plutôt que sur la productivité. Quoi qu'il en soit, j'ai apporté quelques mises à jour mineures à votre code fin: pastebin.com/ManWmNnW
Fredrik Johansson

2

avec cette méthode, vous pouvez obtenir une plage spécifique de chaîne.vous devez passer l'index de démarrage et après ce nombre total de caractères que vous souhaitez.

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

Ceci est ma solution, pas d'avertissement, pas d'erreurs, mais parfait

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'utilisation de encodedOffsetest considérée comme nuisible et sera déconseillée .
Martin R

1

J'espère que cela vous aidera un peu plus: -

var string = "123456789"

Si vous voulez une sous-chaîne après un index particulier.

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

Si vous voulez une sous-chaîne après avoir supprimé une chaîne à la fin.

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

vous pouvez également créer des index avec le code suivant: -

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

0

J'espère que ce serait 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!...]))

Vous pouvez essayer de cette façon et vous obtiendrez de bons résultats.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.