Wie kann ich String Swift-Indizes in Swift 4 verwenden?


294

Ich habe den folgenden einfachen Code in Swift 3 geschrieben:

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

Von Xcode 9 Beta 5 erhalte ich die folgende Warnung:

' substring(to:)' ist veraltet: Bitte verwenden Sie einen StringSlicing-Index mit einem Operator 'Teilbereich von'.

Wie kann dieser Slicing-Index mit Teilbereich von in Swift 4 verwendet werden?


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

Antworten:


375

Sie sollten eine Seite leer lassen , daher der Name "Teilbereich".

let newStr = str[..<index]

Das gleiche gilt für Teilreichweite von Bedienern, lassen Sie einfach die andere Seite leer:

let newStr = str[index...]

Beachten Sie, dass diese Bereichsoperatoren a zurückgeben Substring. Wenn Sie es in einen String konvertieren möchten, verwenden Sie Stringdie Initialisierungsfunktion:

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

Weitere Informationen zu den neuen Teilzeichenfolgen finden Sie hier .


8
str[..<index]gibt a zurück Substring. Wenn du ein sein willst newStr, Stringmusst du schreiben:let newStr = "\(str[..<index])"
Lindemann

12
Die Verwendung der String-Interpolation mit einem Lone Substringist wahrscheinlich etwas verwirrend, da Sie wirklich versuchen, die StringInitialisierung zu erreichen : let newStr = String(str[..<index]).
Gary

5
Das Aktualisieren von Code, bei dem mein 'Index'-Wert einfach eine Ganzzahl war, führt zu einer Fehlermeldung Cannot subscript a value of type 'String' with an index of type 'PartialRangeUpTo<Int>'. Welche Arten von Werten müssen dort verwendet werden?
ConfusionTowers

22
@ConfusionTowers, Swift-String-Indizes sind keine ganzen Zahlen , und das hat sich mit Version 4 nicht geändert. Sie werden wahrscheinlich str[..<str.index(str.startIndex, offsetBy: 8)]etwas Ähnliches benötigen . Denken Sie daran, dass dies str.indexeine zeitlich lineare Operation in Funktion von ist offsetBy.
Zneak

6
@ Zneak Sie wollen wahrscheinlichstr.prefix(8)
Tim Vermeulen

264

Konvertieren Sie die Teilzeichenfolge (Swift 3) in String Slicing (Swift 4).

Beispiele 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, und danke, dass Sie die 3 und 4 Beispiele nebeneinander angegeben haben, erleichtert die Aktualisierung meines Projekts!
Ethan Parker

86

Swift 5, 4

Verwendung

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
Diese Funktionalität sollte standardmäßig schnelles Verhalten sein.
Laimis

4
Auf jeden Fall PR dies in Swift lib: D
OhadM

2
Dies ist eine Lösung für den hässlichsten Teil des Swift.
Dmitry

@Dmitry jemand mochte es nicht, da diese Antwort -2 hat. : D
Dimpiax

Dies ist eine schlechte Antwort, da der Indexoperator die O (n) -Komplexität der Indexfunktion verbirgt. Eine gute Programmier-API verwendet nur einen Index, um eine schnelle Suche zu kennzeichnen.
Ragnarius

38

Kürzere in Swift 4/5:

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

26

Die Konvertierung Ihres Codes in Swift 4 kann auch folgendermaßen erfolgen:

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

Sie können den folgenden Code verwenden, um eine neue Zeichenfolge zu erhalten:

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

17

Teilzeichenfolge (von: Index) Konvertiert in [Index ...]

Überprüfen Sie die Probe

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
Zeichen sind in Swift 4 veraltet. Ich denke, Sie müssen das Beispiel ändern, um den Index für Swift 4
AbuTaareq

Das hat mir geholfen. tnx
user1105951

17

Swift5

(Javas Teilstring-Methode):

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

Verwendungszweck:

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

2
Funktioniert immer noch in Swift 5. Ich suchte nach einem Teilstring im Java-Stil ( fromto to-1, z. B. "Hello".substring(1,4)"ell"). Mit einer kleinen Modifikation ( startIndex..<endIndex) ist dies die beste Lösung, die ich bisher gefunden habe und die genau das mit nur wenigen Codezeilen macht.
Neph

9

Einige nützliche Erweiterungen:

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

Interessant, ich dachte das gleiche. Ist String (Zeile ["http: //" .endIndex ...]) klarer als der veraltete Teilstring? line.substring (von: "http: //" .endIndex) Vielleicht sollten sie Teilzeichenfolgen nicht verwerfen, bis sie das erklärte Ziel einer erstaunlichen Zeichenfolgenbehandlung erreicht haben.
Possen

7

Beispiel für eine uppercasedFirstCharacterConvenience-Eigenschaft in Swift3 und Swift4.

Die Eigenschaft uppercasedFirstCharacterNewzeigt, wie der Index zum Schneiden von Zeichenfolgen in Swift4 verwendet wird.

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
Wenn Sie Teilzeichenfolge (mit: Bereich) -> Selbst [Bereich]
Arsen Vartbaronov

6

Sie können Ihre benutzerdefinierte SubString-Methode mithilfe der Erweiterung der Klasse String wie folgt erstellen:

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

Wenn dies einen endIndex aufnehmen soll, muss es auch in der Lage sein, außerhalb der Grenzen zu arbeiten.
Jay

5

Erstellen von SubString (Präfix und Suffix) aus String mit 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)")
}

Ausgabe

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

Wenn Sie einen Teilstring zwischen zwei Indizes generieren möchten, verwenden Sie:

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

let prefix = str [... <index>] anstelle von str [.. <index>] fehlt ein einzelner Punkt.
AbuTaareq

@AbuTaareq, von welchem ​​sprichst du? Lassen Sie das Präfix = str [.. <Index], es ist perfekt. (Präfixzeichenfolge). Versuchen Sie es auf dem Spielplatz, um mehr Kontext zu erhalten.
Ashis Laha

4

Ich habe eine String-Erweiterung zum Ersetzen von 'String: subString:' geschrieben.

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

}

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

Beispiel Ergebnis : "1511508780012"

PS: Optionale Optionen müssen ausgepackt werden. Bitte fügen Sie bei Bedarf eine Sicherheitsüberprüfung hinzu.


Achtung: Optionale müssen ausgepackt werden. Bitte fügen Sie bei Bedarf eine Sicherheitsüberprüfung hinzu.
Jeevan

3

Beim Programmieren habe ich oft Strings mit einfachem A-Za-z und 0-9. Keine Notwendigkeit für schwierige Indexaktionen. Diese Erweiterung basiert auf den einfachen alten Funktionen für links / mittel / rechts.

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

Großartige Idee!! Traurig, dass es notwendig ist, Swift-Features zu abstrahieren, nur weil sie ständig die Funktionsweise ändern. Vermutlich möchten sie, dass wir uns alle auf Konstrukte anstatt auf Produktivität konzentrieren. Wie auch immer, ich habe einige kleinere Aktualisierungen an Ihrem Feincode vorgenommen
Fredrik Johansson

2

Mit dieser Methode können Sie einen bestimmten Bereich von Zeichenfolgen abrufen. Sie müssen den Startindex und danach die Gesamtzahl der gewünschten Zeichen übergeben.

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

Dies ist meine Lösung, keine Warnung, keine Fehler, aber perfekt

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

Die Verwendung von encodedOffsetwird als schädlich angesehen und veraltet sein .
Martin R

1

Hoffe das hilft wenig mehr: -

var string = "123456789"

Wenn Sie einen Teilstring nach einem bestimmten Index wünschen.

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

Wenn Sie einen Teilstring möchten, nachdem Sie am Ende einen String entfernt haben.

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

Sie können auch Indizes mit dem folgenden Code erstellen: -

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

0

Hoffe es wäre hilfreich.

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

Sie können es auf diese Weise versuchen und erhalten die richtigen Ergebnisse.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.