Wie funktioniert der String-Teilstring in Swift?

354

Ich habe einige meiner alten Codes und Antworten mit Swift 3 aktualisiert, aber als ich zu Swift Strings und Indizierung mit Teilzeichenfolgen kam, wurden die Dinge verwirrend.

Insbesondere habe ich Folgendes versucht:

let str = "Hello, playground"
let prefixRange = str.startIndex..<str.startIndex.advancedBy(5)
let prefix = str.substringWithRange(prefixRange)

wo die zweite Zeile mir den folgenden Fehler gab

Der Wert vom Typ 'String' hat kein Mitglied 'substringWithRange'.

Ich sehe, dass Stringes jetzt die folgenden Methoden gibt:

str.substring(to: String.Index)
str.substring(from: String.Index)
str.substring(with: Range<String.Index>)

Diese haben mich zuerst wirklich verwirrt, also fing ich an, mit Index und Reichweite zu spielen . Dies ist eine Folgefrage und -antwort für Teilzeichenfolgen. Ich füge unten eine Antwort hinzu, um zu zeigen, wie sie verwendet werden.

Suragch
quelle
2
Für diejenigen, die den Teilstring von der Zeichenfolge stackoverflow.com/q/32305891/468724 erhalten möchten
Inder Kumar Rathore
oder Indexzeichenfolge
Leo Dabus

Antworten:

831

Geben Sie hier die Bildbeschreibung ein

Alle folgenden Beispiele verwenden

var str = "Hello, playground"

Swift 4

Strings wurden in Swift 4 ziemlich gründlich überarbeitet. Wenn Sie jetzt einen Teilstring von einem String erhalten, erhalten Sie einen SubstringTyp zurück und nicht einen String. Warum ist das? Zeichenfolgen sind Werttypen in Swift. Das heißt, wenn Sie einen String verwenden, um einen neuen zu erstellen, muss dieser kopiert werden. Dies ist gut für die Stabilität (niemand anderes wird es ohne Ihr Wissen ändern), aber schlecht für die Effizienz.

Ein Teilstring hingegen verweist auf den ursprünglichen String, aus dem er stammt. Hier ist ein Bild aus der Dokumentation, das dies veranschaulicht.

Es ist kein Kopieren erforderlich, daher ist die Verwendung wesentlich effizienter. Stellen Sie sich jedoch vor, Sie hätten eine zehnstellige Teilzeichenfolge aus einer Zeichenfolge mit einer Million Zeichen. Da der Teilstring auf den String verweist, müsste das System den gesamten String so lange festhalten, wie der Teilstring vorhanden ist. Wenn Sie also Ihren Teilstring bearbeitet haben, konvertieren Sie ihn in einen String.

let myString = String(mySubstring)

Dadurch wird nur der Teilstring kopiert und der Speicher mit dem alten String kann zurückgefordert werden . Teilzeichenfolgen (als Typ) sollen von kurzer Dauer sein.

Eine weitere große Verbesserung in Swift 4 ist, dass Strings (wieder) Sammlungen sind. Das bedeutet, dass Sie alles, was Sie mit einer Sammlung tun können, mit einem String tun können (Indizes verwenden, Zeichen durchlaufen, filtern usw.).

Die folgenden Beispiele zeigen, wie Sie einen Teilstring in Swift erhalten.

Teilzeichenfolgen abrufen

Sie können einen Teilstring aus einem String erhalten , indem Indizes oder eine Reihe anderer Methoden (zum Beispiel unter Verwendung von prefix, suffix, split). Sie müssen String.Indexjedoch weiterhin einen IntIndex für den Bereich verwenden und nicht . (Siehe meine andere Antwort, wenn Sie dabei Hilfe benötigen.)

Anfang einer Zeichenfolge

Sie können einen Index verwenden (beachten Sie den einseitigen Bereich von Swift 4):

let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str[..<index] // Hello

oder prefix:

let index = str.index(str.startIndex, offsetBy: 5)
let mySubstring = str.prefix(upTo: index) // Hello

oder noch einfacher:

let mySubstring = str.prefix(5) // Hello

Ende einer Zeichenfolge

Verwenden von Indizes:

let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str[index...] // playground

oder suffix:

let index = str.index(str.endIndex, offsetBy: -10)
let mySubstring = str.suffix(from: index) // playground

oder noch einfacher:

let mySubstring = str.suffix(10) // playground

Beachten Sie, dass suffix(from: index)ich bei der Verwendung von vom Ende an mit zurückzählen musste -10. Dies ist nicht erforderlich, wenn nur suffix(x)die letzten xZeichen eines Strings verwendet werden.

Bereich in einer Zeichenfolge

Auch hier verwenden wir einfach Indizes.

let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let range = start..<end

let mySubstring = str[range]  // play

Konvertieren SubstringinString

Vergessen Sie nicht, wenn Sie bereit sind, Ihren Teilstring zu speichern, sollten Sie ihn in einen konvertieren, Stringdamit der Speicher des alten Strings bereinigt werden kann.

let myString = String(mySubstring)

Verwenden Sie eine IntIndexerweiterung?

Ich zögere, eine Intbasierte Indexerweiterung zu verwenden, nachdem ich den Artikel Strings in Swift 3 von Airspeed Velocity und Ole Begemann gelesen habe . Obwohl Strings in Swift 4 Sammlungen sind, hat das Swift-Team absichtlich keine IntIndizes verwendet. Es ist immer noch String.Index. Dies hat damit zu tun, dass Swift-Zeichen aus einer unterschiedlichen Anzahl von Unicode-Codepunkten bestehen. Der tatsächliche Index muss für jede Zeichenfolge eindeutig berechnet werden.

Ich muss sagen, ich hoffe, dass das Swift-Team String.Indexin Zukunft einen Weg findet, sich zu abstrahieren . Aber bis sie sich dafür entscheiden, ihre API zu verwenden. Es hilft mir, mich daran zu erinnern, dass String-Manipulationen nicht nur einfache IntIndex-Lookups sind.

Suragch
quelle
9
Danke für die Beschreibung. Gut verdiente Uprates. Apple hat dies überkompliziert. Die Teilzeichenfolge sollte so einfach sein wie die Zeichenfolge string.substring [von ... bis].
Teddy
Wirklich gute Erklärung. außer einer kleinen Sache garbage collected;-) Ich hoffe, die Leute hier wissen, dass es in Swift keine Müllabfuhr gibt.
Christian Anchor Dampf
@ChristianAnchorDampf, Danke, dass du dir die Zeit für einen Kommentar genommen hast. Ich habe Müll gesammelt. Wie ist der neue Wortlaut?
Suragch
Was für eine erstaunliche Antwort, Sir!
Davidv
194

Ich bin wirklich frustriert über Swifts String-Zugriffsmodell: Alles muss ein sein Index. Alles, was ich möchte, ist, auf das i-te Zeichen der Zeichenfolge zuzugreifen Int, nicht auf den ungeschickten Index und das Fortschreiten (was sich mit jeder Hauptversion ändert). Also habe ich eine Erweiterung gemacht zu String:

extension String {
    func index(from: Int) -> Index {
        return self.index(startIndex, offsetBy: from)
    }

    func substring(from: Int) -> String {
        let fromIndex = index(from: from)
        return String(self[fromIndex...])
    }

    func substring(to: Int) -> String {
        let toIndex = index(from: to)
        return String(self[..<toIndex])
    }

    func substring(with r: Range<Int>) -> String {
        let startIndex = index(from: r.lowerBound)
        let endIndex = index(from: r.upperBound)
        return String(self[startIndex..<endIndex])
    }
}

let str = "Hello, playground"
print(str.substring(from: 7))         // playground
print(str.substring(to: 5))           // Hello
print(str.substring(with: 7..<11))    // play
Code anders
quelle
5
Die Indizes sind sehr nützlich, da ein Zeichen mehr als ein Byte umfassen kann. Versuchen Sielet str = "🇨🇭🇩🇪🇺🇸Hello" print(str.substring(to: 2))
vadian
110
Ja, ich verstehe, dass ein Zeichen (dh ein erweiterter Graphemcluster ) mehrere Bytes aufnehmen kann. Meine Frustration ist, warum wir die ausführliche Index-Advancing-Methode verwenden müssen, um auf die Zeichen einer Zeichenfolge zuzugreifen. Warum kann das Swift-Team der Kernbibliothek nicht einfach einige Überladungen hinzufügen, um sie zu abstrahieren? Wenn ich tippe str[5], möchte ich auf das Zeichen in Index 5 zugreifen, unabhängig davon, welches Zeichen es zu sein scheint oder wie viele Bytes es benötigt. Geht es bei Swift nicht nur um die Produktivität der Entwickler?
Code anders
6
@RenniePet Ich glaube, Apple erkennt das Problem und es kommen Änderungen. Auf der Swift Evolution-Seite auf GitHub heißt es: "Swift 4 versucht, Zeichenfolgen leistungsfähiger und benutzerfreundlicher zu machen, wobei die Unicode-Korrektheit standardmäßig beibehalten wird." Es ist vage, aber lassen Sie uns unsere Hoffnungen aufrecht erhalten
Code Different
3
@CodeDifferent, warum Apple keinen Zugriff auf tiefgestellte Zeichen hinzugefügt hat? Damit die Leute verstehen, dass es schlecht ist, das zu tun. Wenn Sie für i in 0..string.count mit Indizes arbeiten würden, die eine Doppelschleife wären, müsste der Index unter der Haube jedes Byte der Zeichenfolge durchlaufen, um herauszufinden, welches das nächste Zeichen ist. Wenn Sie eine Schleife mit Index ausführen, durchlaufen Sie die Zeichenfolge nur einmal. Übrigens, ich hasse das selbst, aber das ist der Grund dafür, dass der Index nicht schnell auf String verfügbar ist.
Raimundas Sakalauskas
4
@RaimundasSakalauskas dieses Argument fliegt nicht an mir vorbei. C # hat sowohl Unicode-Korrektheit als auch Ganzzahl-Subskription, was sehr praktisch ist. In Swift 1 wollte Apple, dass Entwickler countElement(str)die Länge ermitteln. In Swift 3 hat Apple einen String erstellt, der nicht den Anforderungen entspricht, Sequenceund alle dazu gezwungen, ihn str.charactersstattdessen zu verwenden . Diese Jungs haben keine Angst vor Änderungen. Ihre Sturheit bei der Ganzzahl-Subskription ist wirklich schwer zu verstehen
Code Different
102

Swift 5-Erweiterung:

extension String {
    subscript(_ range: CountableRange<Int>) -> String {
        let start = index(startIndex, offsetBy: max(0, range.lowerBound))
        let end = index(start, offsetBy: min(self.count - range.lowerBound, 
                                             range.upperBound - range.lowerBound))
        return String(self[start..<end])
    }

    subscript(_ range: CountablePartialRangeFrom<Int>) -> String {
        let start = index(startIndex, offsetBy: max(0, range.lowerBound))
         return String(self[start...])
    }
}

Verwendungszweck:

let s = "hello"
s[0..<3] // "hel"
s[3...]  // "lo"

Oder Unicode:

let s = "😎🤣😋"
s[0..<1] // "😎"
Lou Zell
quelle
2
Viel besser, danke, dass du diese Erweiterung gepostet hast! Ich denke, Swift kommt aus Python und ist viel schwieriger als nötig, sich daran zu gewöhnen. Es scheint, dass es für Menschen, die von Ziel C nach Swift in die andere Richtung gehen, eine positivere Bestätigung gibt.
user3064009
1
@Leon Ich habe es gerade entfernt. Vor 4.1 countwar nur verfügbar amself.characters
Lou Zell
1
Gibt es Fallstricke bei dieser speziellen Erweiterung? Warum hat Apple so etwas nicht gemacht?
Andz
1
@Andz es ist sehr ineffizient. Es beginnt am Anfang der Zeichenfolge - zweimal - und muss jedes Zeichen von dort bis "Bereich" analysieren - zweimal.
Kareman
3
Sie müssen auch eine ErweiterungCountableClosedRange<Int> hinzufügen , die eine benötigt, wenn Sie z s[0...2].
Chris Frederick
24

Swift 4 & 5:

extension String {
  subscript(_ i: Int) -> String {
    let idx1 = index(startIndex, offsetBy: i)
    let idx2 = index(idx1, offsetBy: 1)
    return String(self[idx1..<idx2])
  }

  subscript (r: Range<Int>) -> String {
    let start = index(startIndex, offsetBy: r.lowerBound)
    let end = index(startIndex, offsetBy: r.upperBound)
    return String(self[start ..< end])
  }

  subscript (r: CountableClosedRange<Int>) -> String {
    let startIndex =  self.index(self.startIndex, offsetBy: r.lowerBound)
    let endIndex = self.index(startIndex, offsetBy: r.upperBound - r.lowerBound)
    return String(self[startIndex...endIndex])
  }
}

Wie man es benutzt:

"abcde" [0] -> "a"

"abcde" [0 ... 2] -> "abc"

"abcde" [2 .. <4] -> "cd"

Souf ROCHDI
quelle
20

Swift 4

In Swift 4 Stringentspricht Collection. Statt substringsollten wir jetzt einen verwenden subscript.Also , wenn Sie nur das Wort ausschneiden möchten "play"aus "Hello, playground", können Sie es wie folgt tun könnte:

var str = "Hello, playground"
let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let result = str[start..<end] // The result is of type Substring

Es ist interessant zu wissen, dass Sie dadurch ein Substringstatt eines erhalten String. Dies ist schnell und effizient, da Substringder Speicher mit dem ursprünglichen String geteilt wird. Das Teilen von Speicher auf diese Weise kann jedoch auch leicht zu Speicherverlusten führen.

Aus diesem Grund sollten Sie das Ergebnis in einen neuen String kopieren, sobald Sie den ursprünglichen String bereinigen möchten. Sie können dies mit dem normalen Konstruktor tun:

let newString = String(result)

Weitere Informationen zur neuen SubstringKlasse finden Sie in der [Apple-Dokumentation]. 1

Wenn Sie beispielsweise a Rangeals Ergebnis von a erhalten NSRegularExpression, können Sie die folgende Erweiterung verwenden:

extension String {

    subscript(_ range: NSRange) -> String {
        let start = self.index(self.startIndex, offsetBy: range.lowerBound)
        let end = self.index(self.startIndex, offsetBy: range.upperBound)
        let subString = self[start..<end]
        return String(subString)
    }

}
gebirgsbärbel
quelle
Ihr Code stürzt ab, wenn range.upperBound> Länge der Zeichenfolge ist. Auch eine Beispielverwendung wäre hilfreich gewesen, da ich mit Indizes in Swift nicht vertraut war. Sie könnten so etwas wie datePartOnly = "2018-01-04-08: 00" [NSMakeRange (0, 10)] einfügen. Davon abgesehen sehr schöne Antwort, +1 :).
DCP
Heutzutage ist es diese seltsame Sache: text[Range( nsRange , in: text)!]
Fattie
10

Hier ist eine Funktion, die den Teilstring eines bestimmten Teilstrings zurückgibt, wenn Start- und Endindizes bereitgestellt werden. Als vollständige Referenz können Sie die unten angegebenen Links besuchen.

func substring(string: String, fromIndex: Int, toIndex: Int) -> String? {
    if fromIndex < toIndex && toIndex < string.count /*use string.characters.count for swift3*/{
        let startIndex = string.index(string.startIndex, offsetBy: fromIndex)
        let endIndex = string.index(string.startIndex, offsetBy: toIndex)
        return String(string[startIndex..<endIndex])
    }else{
        return nil
    }
}

Hier ist ein Link zu dem Blog-Beitrag, den ich erstellt habe, um die Manipulation von Strings schnell zu erledigen. String-Manipulation in Swift (Deckt auch Swift 4 ab)

Oder Sie können diesen Kern auf Github sehen

Nikesh Jha
quelle
9

Ich hatte die gleiche anfängliche Reaktion. Ich war auch frustriert darüber, wie sich Syntax und Objekte in jeder Hauptversion so drastisch ändern.

Aus Erfahrung wurde mir jedoch klar, dass ich letztendlich immer unter den Folgen des Versuchs leide, "Veränderungen" zu bekämpfen, wie den Umgang mit Multi-Byte-Zeichen, was unvermeidlich ist, wenn man ein globales Publikum betrachtet.

Deshalb habe ich mich entschlossen, die Bemühungen der Apple-Ingenieure anzuerkennen und zu respektieren und meinen Teil dazu beizutragen, ihre Denkweise zu verstehen, als sie diesen "schrecklichen" Ansatz entwickelten.

Anstatt Erweiterungen zu erstellen, die nur eine Problemumgehung darstellen, um Ihnen das Leben zu erleichtern (ich sage nicht, dass sie falsch oder teuer sind), sollten Sie herausfinden, wie Strings jetzt funktionieren.

Zum Beispiel hatte ich diesen Code, der an Swift 2.2 arbeitete:

let rString = cString.substringToIndex(2)
let gString = (cString.substringFromIndex(2) as NSString).substringToIndex(2)
let bString = (cString.substringFromIndex(4) as NSString).substringToIndex(2)

und nachdem ich es aufgegeben hatte, den gleichen Ansatz zum Beispiel mit Substrings zum Laufen zu bringen, verstand ich endlich das Konzept, Strings als bidirektionale Sammlung zu behandeln, für die ich am Ende dieselbe Version desselben Codes erhielt:

let rString = String(cString.characters.prefix(2))
cString = String(cString.characters.dropFirst(2))
let gString = String(cString.characters.prefix(2))
cString = String(cString.characters.dropFirst(2))
let bString = String(cString.characters.prefix(2))

Ich hoffe das trägt dazu bei ...

Rio Bautista
quelle
1
Die Behandlung eines komplexen Problems bedeutet nicht, dass die Lösung elegant sein könnte. Auch hier verstehe ich das Problem, aber die gesamte String-Klasse und der Umgang damit sind einfach schrecklich.
Unentschlossenheit
5

Gleiche Frustration, das sollte nicht so schwer sein ...

Ich habe dieses Beispiel zusammengestellt, um Positionen für Teilzeichenfolgen aus größerem Text abzurufen:

//
// Play with finding substrings returning an array of the non-unique words and positions in text
//
//

import UIKit

let Bigstring = "Why is it so hard to find substrings in Swift3"
let searchStrs : Array<String>? = ["Why", "substrings", "Swift3"]

FindSubString(inputStr: Bigstring, subStrings: searchStrs)


func FindSubString(inputStr : String, subStrings: Array<String>?) ->    Array<(String, Int, Int)> {
    var resultArray : Array<(String, Int, Int)> = []
    for i: Int in 0...(subStrings?.count)!-1 {
        if inputStr.contains((subStrings?[i])!) {
            let range: Range<String.Index> = inputStr.range(of: subStrings![i])!
            let lPos = inputStr.distance(from: inputStr.startIndex, to: range.lowerBound)
            let uPos = inputStr.distance(from: inputStr.startIndex, to: range.upperBound)
            let element = ((subStrings?[i])! as String, lPos, uPos)
            resultArray.append(element)
        }
    }
    for words in resultArray {
        print(words)
    }
    return resultArray
}

gibt zurück ("Warum", 0, 3) ("Teilzeichenfolgen", 26, 36) ("Swift3", 40, 46)

Großer Däne
quelle
3
Das ist etwas Code, erklärt aber nicht wirklich, wie String-Indizierung und Teilzeichenfolgen in swift3 funktionieren.
Robert
5

Ich bin neu in Swift 3, aber wenn ich die String(Index-) Syntax nach Analogie suche, denke ich, dass Index wie ein "Zeiger" ist, der auf Zeichenfolge beschränkt ist, und Int kann als unabhängiges Objekt helfen. Mit der Syntax base + offset können wir das i-te Zeichen aus der Zeichenfolge mit dem folgenden Code abrufen:

let s = "abcdefghi"
let i = 2
print (s[s.index(s.startIndex, offsetBy:i)])
// print c

Für einen Bereich von Zeichen (Indizes) aus Zeichenfolgen mithilfe der String (Bereich) -Syntax können wir mit dem folgenden Code vom i-ten zum f-ten Zeichen gelangen:

let f = 6
print (s[s.index(s.startIndex, offsetBy:i )..<s.index(s.startIndex, offsetBy:f+1 )])
//print cdefg

Für einen Teilstring (Bereich) aus einem String mit String.substring (Bereich) können wir den Teilstring mit dem folgenden Code abrufen:

print (s.substring (with:s.index(s.startIndex, offsetBy:i )..<s.index(s.startIndex, offsetBy:f+1 ) ) )
//print cdefg

Anmerkungen:

  1. Das i-te und das f-te beginnen mit 0.

  2. Zum fünften verwende ich offsetBY: f + 1, da der Bereich der Abonnementverwendung .. <(halboffener Operator) nicht die fünfte Position enthält.

  3. Natürlich müssen Validierungsfehler wie ungültiger Index enthalten sein.

Nelson Mizutani
quelle
5

Swift 4+

extension String {
    func take(_ n: Int) -> String {
        guard n >= 0 else {
            fatalError("n should never negative")
        }
        let index = self.index(self.startIndex, offsetBy: min(n, self.count))
        return String(self[..<index])
    }
}

Gibt eine Teilsequenz der ersten n Zeichen oder der gesamten Zeichenfolge zurück, wenn die Zeichenfolge kürzer ist. (inspiriert von: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/take.html )

Beispiel:

let text = "Hello, World!"
let substring = text.take(5) //Hello
Peter Kreinz
quelle
4

Ich denke ziemlich mechanisch. Hier sind die Grundlagen ...

Swift 4 Swift 5

  let t = "abracadabra"

  let start1 = t.index(t.startIndex, offsetBy:0)
  let   end1 = t.index(t.endIndex, offsetBy:-5)
  let start2 = t.index(t.endIndex, offsetBy:-5)
  let   end2 = t.index(t.endIndex, offsetBy:0)

  let t2 = t[start1 ..< end1]
  let t3 = t[start2 ..< end2]                

  //or a shorter form 

  let t4 = t[..<end1]
  let t5 = t[start2...]

  print("\(t2) \(t3) \(t)")
  print("\(t4) \(t5) \(t)")

  // result:
  // abraca dabra abracadabra

Das Ergebnis ist eine Teilzeichenfolge, was bedeutet, dass sie Teil der ursprünglichen Zeichenfolge ist. Um eine vollständige separate Zeichenfolge zu erhalten, verwenden Sie einfach z

    String(t3)
    String(t4)

Das benutze ich:

    let mid = t.index(t.endIndex, offsetBy:-5)
    let firstHalf = t[..<mid]
    let secondHalf = t[mid...]
t1ser
quelle
3

Swift 4

extension String {
    subscript(_ i: Int) -> String {
        let idx1 = index(startIndex, offsetBy: i)
        let idx2 = index(idx1, offsetBy: 1)
        return String(self[idx1..<idx2])
    }
}

let s = "hello"

s[0]    // h
s[1]    // e
s[2]    // l
s[3]    // l
s[4]    // o
FlowUI. SimpleUITesting.com
quelle
2

Ich habe dafür eine einfache Erweiterung erstellt (Swift 3)

extension String {
    func substring(location: Int, length: Int) -> String? {
        guard characters.count >= location + length else { return nil }
        let start = index(startIndex, offsetBy: location)
        let end = index(startIndex, offsetBy: location + length)
        return substring(with: start..<end)
    }
}
Lucas Algarra
quelle
2

Hier ist eine allgemeinere Implementierung:

Diese Technik entspricht immer noch indexden Standards von Swift und impliziert einen vollständigen Charakter.

extension String
{
    func subString <R> (_ range: R) -> String? where R : RangeExpression, String.Index == R.Bound
    {
        return String(self[range])
    }

    func index(at: Int) -> Index
    {
        return self.index(self.startIndex, offsetBy: at)
    }
}

So unterzeichnen Sie die Zeichenfolge vom 3. Zeichen:

let item = "Fred looks funny"
item.subString(item.index(at: 2)...) // "ed looks funny"

Ich habe Kamel verwendet, subStringum anzuzeigen, dass es a Stringund nicht a zurückgibt Substring.

Leslie Godwin
quelle
2

Aufbauend auf dem oben Gesagten musste ich eine Zeichenfolge bei einem nicht druckbaren Zeichen teilen und das nicht druckbare Zeichen löschen. Ich habe zwei Methoden entwickelt:

var str = "abc\u{1A}12345sdf"
let range1: Range<String.Index> = str.range(of: "\u{1A}")!
let index1: Int = str.distance(from: str.startIndex, to: range1.lowerBound)
let start = str.index(str.startIndex, offsetBy: index1)
let end = str.index(str.endIndex, offsetBy: -0)
let result = str[start..<end] // The result is of type Substring
let firstStr = str[str.startIndex..<range1.lowerBound]

was ich mit einigen der obigen Antworten zusammengestellt habe.

Da ein String eine Sammlung ist, habe ich dann Folgendes getan:

var fString = String()
for (n,c) in str.enumerated(){

*if c == "\u{1A}" {
    print(fString);
    let lString = str.dropFirst(n + 1)
    print(lString)
    break
   }
 fString += String(c)
}*

Was für mich intuitiver war. Welches ist das Beste? Ich kann es nicht sagen. Beide arbeiten mit Swift 5

Jeremy Andrews
quelle
Danke für deine Antwort. Ist etwas anderes an Strings in Swift 5? Ich hatte noch keine Zeit, damit herumzuspielen.
Suragch
Sie sagen es, aber ich hatte keine Gelegenheit, es zu untersuchen.
Jeremy Andrews
1

Swift 4

"Teilzeichenfolge" ( https://developer.apple.com/documentation/swift/substring ):

let greeting = "Hi there! It's nice to meet you! 👋"
let endOfSentence = greeting.index(of: "!")!
let firstSentence = greeting[...endOfSentence]
// firstSentence == "Hi there!"

Beispiel für die Erweiterung String:

private typealias HowDoYouLikeThatElonMusk = String
private extension HowDoYouLikeThatElonMusk {

    subscript(_ from: Character?, _ to: Character?, _ include: Bool) -> String? {
        if let _from: Character = from, let _to: Character = to {
            let dynamicSourceForEnd: String = (_from == _to ? String(self.reversed()) : self)
            guard let startOfSentence: String.Index = self.index(of: _from),
                let endOfSentence: String.Index = dynamicSourceForEnd.index(of: _to) else {
                return nil
            }

            let result: String = String(self[startOfSentence...endOfSentence])
            if include == false {
                guard result.count > 2 else {
                        return nil
                }
                return String(result[result.index(result.startIndex, offsetBy: 1)..<result.index(result.endIndex, offsetBy: -1)])
            }
            return result
        } else if let _from: Character = from {
            guard let startOfSentence: String.Index = self.index(of: _from) else {
                return nil
            }
            let result: String = String(self[startOfSentence...])
            if include == false {
                guard result.count > 1 else {
                    return nil
                }
                return String(result[result.index(result.startIndex, offsetBy: 1)...])
            }
            return result
        } else if let _to: Character = to {
            guard let endOfSentence: String.Index = self.index(of: _to) else {
                    return nil
            }
            let result: String = String(self[...endOfSentence])
            if include == false {
                guard result.count > 1 else {
                    return nil
                }
                return String(result[..<result.index(result.endIndex, offsetBy: -1)])
            }
            return result
        }
        return nil
    }
}

Beispiel für die Verwendung der Erweiterung String:

let source =                                   ">>>01234..56789<<<"
// include = true
var from =          source["3", nil, true]  //       "34..56789<<<"
var to =            source[nil, "6", true]  // ">>>01234..56"
var fromTo =        source["3", "6", true]  //       "34..56"
let notFound =      source["a", nil, true]  // nil
// include = false
from =              source["3", nil, false] //        "4..56789<<<"
to =                source[nil, "6", false] // ">>>01234..5"
fromTo =            source["3", "6", false] //        "4..5"
let outOfBounds =   source[".", ".", false] // nil

let str = "Hello, playground"
let hello = str[nil, ",", false] // "Hello"
CAHbl463
quelle
-1

Swift 5
let desiredIndex: Int = 7 let substring = str[String.Index(encodedOffset: desiredIndex)...]
Diese Teilzeichenfolgenvariable gibt Ihnen das Ergebnis.
Einfach hier wird Int in Index konvertiert und dann können Sie die Strings teilen. Es sei denn, Sie erhalten Fehler.

Wimukthi Rajapaksha
quelle
2
Das ist falsch. Ein Zeichen kann aus einem oder mehreren Bytes bestehen. Es funktioniert nur mit ASCII-Text.
Leo Dabus