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 String
es 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.
Antworten:
Alle folgenden Beispiele verwenden
Swift 4
Strings wurden in Swift 4 ziemlich gründlich überarbeitet. Wenn Sie jetzt einen Teilstring von einem String erhalten, erhalten Sie einen
Substring
Typ zurück und nicht einenString
. 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.
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üssenString.Index
jedoch weiterhin einenInt
Index 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):
oder
prefix
:oder noch einfacher:
Ende einer Zeichenfolge
Verwenden von Indizes:
oder
suffix
:oder noch einfacher:
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 nursuffix(x)
die letztenx
Zeichen eines Strings verwendet werden.Bereich in einer Zeichenfolge
Auch hier verwenden wir einfach Indizes.
Konvertieren
Substring
inString
Vergessen Sie nicht, wenn Sie bereit sind, Ihren Teilstring zu speichern, sollten Sie ihn in einen konvertieren,
String
damit der Speicher des alten Strings bereinigt werden kann.Verwenden Sie eine
Int
Indexerweiterung?Ich zögere, eine
Int
basierte 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 keineInt
Indizes verwendet. Es ist immer nochString.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.Index
in 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 einfacheInt
Index-Lookups sind.quelle
garbage collected
;-) Ich hoffe, die Leute hier wissen, dass es in Swift keine Müllabfuhr gibt.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 zuzugreifenInt
, nicht auf den ungeschickten Index und das Fortschreiten (was sich mit jeder Hauptversion ändert). Also habe ich eine Erweiterung gemacht zuString
:quelle
let str = "🇨🇭🇩🇪🇺🇸Hello"
print(str.substring(to: 2))
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?countElement(str)
die Länge ermitteln. In Swift 3 hat Apple einen String erstellt, der nicht den Anforderungen entspricht,Sequence
und alle dazu gezwungen, ihnstr.characters
stattdessen zu verwenden . Diese Jungs haben keine Angst vor Änderungen. Ihre Sturheit bei der Ganzzahl-Subskription ist wirklich schwer zu verstehenSwift 5-Erweiterung:
Verwendungszweck:
Oder Unicode:
quelle
count
war nur verfügbar amself.characters
CountableClosedRange<Int>
hinzufügen , die eine benötigt, wenn Sie zs[0...2]
.Swift 4 & 5:
Wie man es benutzt:
quelle
Swift 4
In Swift 4
String
entsprichtCollection
. Stattsubstring
sollten wir jetzt einen verwendensubscript.
Also , wenn Sie nur das Wort ausschneiden möchten"play"
aus"Hello, playground"
, können Sie es wie folgt tun könnte:Es ist interessant zu wissen, dass Sie dadurch ein
Substring
statt eines erhaltenString
. Dies ist schnell und effizient, daSubstring
der 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:
Weitere Informationen zur neuen
Substring
Klasse finden Sie in der [Apple-Dokumentation]. 1Wenn Sie beispielsweise a
Range
als Ergebnis von a erhaltenNSRegularExpression
, können Sie die folgende Erweiterung verwenden:quelle
text[Range( nsRange , in: text)!]
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.
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
quelle
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:
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:
Ich hoffe das trägt dazu bei ...
quelle
Gleiche Frustration, das sollte nicht so schwer sein ...
Ich habe dieses Beispiel zusammengestellt, um Positionen für Teilzeichenfolgen aus größerem Text abzurufen:
gibt zurück ("Warum", 0, 3) ("Teilzeichenfolgen", 26, 36) ("Swift3", 40, 46)
quelle
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: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:
Für einen Teilstring (Bereich) aus einem String mit String.substring (Bereich) können wir den Teilstring mit dem folgenden Code abrufen:
Anmerkungen:
Das i-te und das f-te beginnen mit 0.
Zum fünften verwende ich offsetBY: f + 1, da der Bereich der Abonnementverwendung .. <(halboffener Operator) nicht die fünfte Position enthält.
Natürlich müssen Validierungsfehler wie ungültiger Index enthalten sein.
quelle
Swift 4+
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:
quelle
Ich denke ziemlich mechanisch. Hier sind die Grundlagen ...
Swift 4 Swift 5
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
Das benutze ich:
quelle
Swift 4
quelle
Ich habe dafür eine einfache Erweiterung erstellt (Swift 3)
quelle
Hier ist eine allgemeinere Implementierung:
Diese Technik entspricht immer noch
index
den Standards von Swift und impliziert einen vollständigen Charakter.So unterzeichnen Sie die Zeichenfolge vom 3. Zeichen:
Ich habe Kamel verwendet,
subString
um anzuzeigen, dass es aString
und nicht a zurückgibtSubstring
.quelle
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:
was ich mit einigen der obigen Antworten zusammengestellt habe.
Da ein String eine Sammlung ist, habe ich dann Folgendes getan:
Was für mich intuitiver war. Welches ist das Beste? Ich kann es nicht sagen. Beide arbeiten mit Swift 5
quelle
Swift 4
"Teilzeichenfolge" ( https://developer.apple.com/documentation/swift/substring ):
Beispiel für die Erweiterung String:
Beispiel für die Verwendung der Erweiterung String:
quelle
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.
quelle