Wie funktioniert ein String-Teilstring in Swift?

Ich habe einen Teil meines alten Codes aktualisiert und auf Swift 3 reagiert, aber als ich mit Padding zu Swift Strings und Indexing kam, wurde alles verwirrend.

Ich habe insbesondere 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 des Typs 'String' hat nicht die Unterzeichenfolge 'WithRange'.

Ich sehe, dass der String jetzt die folgenden Methoden hat:

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

Zuerst verwirrte es mich, also begann ich mit dem Index und dem Bereich zu spielen . Dies ist die Frage und Antwort für den Teilstring. Ich füge die Antwort unten hinzu, um zu zeigen, wie sie verwendet werden.

241
24 сент. von Suragch am 24. September eingestellt . 2016-09-24 17:17 2016 um 17:17 Uhr 2016-09-24 17:17 Uhr
@ 12 Antworten
24 сент. Die Antwort wird von Suragch am 24. September gegeben . 2016-09-24 17:17 2016 um 17:17 Uhr 2016-09-24 17:17 Uhr

Ich bin vom Swift String Access-Modell wirklich enttäuscht: Alles sollte ein Index . Alles, was ich möchte, ist, auf das i-te Zeichen der Zeichenfolge mit Int zuzugreifen, anstatt mit einem unhandlichen Index und Fortschritt (was bei jeder Hauptversion der Fall ist). Daher habe ich eine Erweiterung für 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 substring(from: fromIndex) } func substring(to: Int) -> String { let toIndex = index(from: to) return substring(to: toIndex) } func substring(with r: Range<Int>) -> String { let startIndex = index(from: r.lowerBound) let endIndex = index(from: r.upperBound) return substring(with: 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 
140
24 сент. Die Antwort lautet Code Different 24. September 2016-09-24 17:55 '16 um 17:55 Uhr 2016-09-24 17:55

Swift 4 Erweiterung:

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

Verwenden:

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

Oder unicode:

 let s = "😎🤣😋" s[0..<1] // "😎" 
40
09 сент. Die Antwort gibt Lou Zell Sep 09 2017-09-09 20:06 '17 am 20:06 2017-09-09 20:06

Schnell 4

In Fast 4 String stimmt die Collection überein. Anstelle der substring wir jetzt den subscript. Wenn Sie also nur das Wort "play" von "Hello, playground" ausschneiden möchten, können Sie dies wie folgt tun:

 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 Substring anstelle eines Substring einen Substring . Dies ist schnell und effizient, da Substring seinen Speicher mit der Substring teilt. Die gemeinsame Nutzung von Speicher auf diese Weise kann jedoch leicht zu Speicherverlusten führen.

Deshalb sollten Sie das Ergebnis in eine neue Zeile kopieren, sobald Sie die Quellzeile löschen möchten. Sie können dies mit dem üblichen Konstruktor tun:

 let newString = String(result) 

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

Wenn Sie beispielsweise Range als Ergebnis von 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) } } 
16
20 сент. Antwort gegeben an gebirgsbärbel 20 Sep. 2017-09-20 18:02 '17 um 6:02 pm 2017-09-20 18:02

Ich hatte die gleiche erste Reaktion. Ich war auch verärgert, dass sich die Syntax und die Objekte in allen großen Releases so drastisch ändern.

Aus Erfahrung lernte ich jedoch, dass ich immer wieder unter den Konsequenzen leide, wenn man versucht, "Veränderung" zu bekämpfen, wie bei Multibyte-Charakteren. Dies ist unvermeidlich, wenn man das globale Publikum betrachtet.

Also entschied ich mich, die Bemühungen der Apple-Ingenieure anzuerkennen und zu respektieren und meinen eigenen Teil beizutragen, indem ich deren Denkweise verstand, als sie diesen "schrecklichen" Ansatz fanden.

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

Zum Beispiel hatte ich diesen Code, der auf Swift 2.2 funktionierte:

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

Nachdem ich mich geweigert hatte, denselben Ansatz zu verwenden, zum Beispiel die Verwendung von Teilzeichenfolgen, verstand ich schließlich das Konzept der Zeichenkettenbehandlung als bidirektionale Sammlung, für die ich diese Version des gleichen Codes vervollständigte:

 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 hilft ...

7
11 нояб. Die Antwort wird von Rio Bautista 11. November gegeben. 2016-11-11 06:19 '16 am 6:19 2016-11-11 06:19

Ich bin neu in Swift 3, aber wenn ich die String (Index) -Syntax für Analogien betrachte, glaube ich, dass der Index wie ein "Zeiger" ist, der auf einen String begrenzt ist, und Int als unabhängiges Objekt helfen kann. Mit der Syntax base + offset können wir das i-te Zeichen aus dem String mit dem folgenden Code abrufen:

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

Für einen Zeichenbereich (Indizes) aus einem String mit der Syntax String (Bereich) können wir vom i-ten zum f-ten Zeichen mit folgendem Code wechseln:

 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 folgendem Code erhalten:

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

Anmerkungen:

  • i-th und f-th beginnen mit 0.

  • In f-te verwende ich offsetBY: f + 1, da der Subskriptionsbereich .. <(halboffener Operator) die f-te Position nicht enthält.

  • Natürlich sollte auch eine Fehlerprüfung enthalten sein, beispielsweise ein ungültiger Index.

5
14 апр. Die Antwort gibt Nelson Mizutani am 14. April. 2017-04-14 00:35 '17 um 0:35 2017-04-14 00:35

Hier ist eine Funktion, die eine Teilzeichenfolge einer bestimmten Teilzeichenfolge zurückgibt, wenn der Start- und Endindex angegeben wird. Für eine vollständige Referenz können Sie die folgenden Links lesen.

 func substring(string: String, fromIndex: Int, toIndex: Int) -> String? { if fromIndex < toIndex  toIndex < string.count { 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 einem Blogpost, den ich erstellt habe, um mit schnellen String-Manipulationen fertig zu werden. Schnelle Saitenmanipulation (deckt auch Swift 4 ab)

Oder Sie können diesen Sinn auf Github sehen

5
11 авг. Die Antwort wird von Nikesh Jha 11 Aug gegeben. 2017-08-11 10:02 '17 am 10:02 2017-08-11 10:02

Die gleiche Enttäuschung sollte es nicht so schwer sein ...

Ich habe dieses Beispiel zusammengestellt, um Positionen für Teilstrings aus einem größeren Text zu erhalten:

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

Rückgabe ("Warum", 0, 3) ("Teilstrings", 26, 36) ("Swift3", 40, 46)

4
11 дек. Die Antwort wird am 11. Dezember in Tall Dane gegeben. 2016-12-11 23:40 '16 um 23:40 Uhr 2016-12-11 23:40

Ich habe eine einfache Erweiterung dafür 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) } } 
1
28 июля '17 в 21:52 2017-07-28 21:52 Die Antwort wird von Lucas Algarra 28. Juli 17 um 21:52 2017-07-28 21:52 gegeben

Schnell 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 
1
15 февр. Die Antwort wird gegeben iOS Kalenderansicht OnMyProfile 15 Feb. 2018-02-15 06:59 '18 at 6:59 2018-15-15 06:59

Dies ist eine allgemeinere Implementierung:

Diese Methode verwendet immer noch den index , um die Swift-Standards beizubehalten und impliziert den vollen 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) } } 

Für den Teilstring des dritten Zeichens:

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

Ich habe den camel subString um anzuzeigen, dass ein String und kein Substring .

0
18 окт. Antwort von Leslie Godwin am 18. Oktober. 2018-10-18 19:22 '18 um 19:22 Uhr 2018-10-18 19:22

Schnell 4

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

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

Beispiel für eine Stringerweiterung:

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

Ein Beispiel für die Verwendung der String-Erweiterung:

 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" 
0
07 июня '18 в 0:02 2018-06-07 00:02 Die Antwort wird gegeben CAHbl463 07. Juni 18 um 0:02 2018-06-07 00:02

Andere Fragen zu Tags oder Frage stellen