Swift: So erhalten Sie Teilzeichenfolgen vom Anfang bis zum letzten Zeichenindex

110

Ich möchte lernen, wie man eine Zeichenfolge am besten / einfachsten in eine andere Zeichenfolge umwandelt, jedoch nur mit einer Teilmenge, beginnend am Anfang und bis zum letzten Index eines Zeichens.

Konvertieren Sie beispielsweise "www.stackoverflow.com" in "www.stackoverflow". Welches Code-Snippet würde das tun und am schnellsten sein? (Ich hoffe, dass dies keine Debatte bringt, aber ich kann keine gute Lektion zum Umgang mit Teilzeichenfolgen in Swift finden.

Jason Hocker
quelle

Antworten:

202

Einfach rückwärts zugreifen

Der beste Weg ist, substringToIndexkombiniert mit dem zu verwendenendIndex Eigenschaft und der advanceglobalen Funktion.

var string1 = "www.stackoverflow.com"

var index1 = advance(string1.endIndex, -4)

var substring1 = string1.substringToIndex(index1)

Auf der Suche nach einer Saite von hinten

Verwenden rangeOfStringund einstellen optionsauf.BackwardsSearch

var string2 = "www.stackoverflow.com"

var index2 = string2.rangeOfString(".", options: .BackwardsSearch)?.startIndex

var substring2 = string2.substringToIndex(index2!)

Keine Erweiterungen, reine Redewendung Swift

Swift 2.0

advanceist jetzt ein Teil von Indexund heißt advancedBy. Du machst es wie:

var string1 = "www.stackoverflow.com"

var index1 = string1.endIndex.advancedBy(-4)

var substring1 = string1.substringToIndex(index1)

Swift 3.0

Sie können nicht nennen advancedByauf eine , Stringweil sie variabler Größe Elemente. Du musst benutzen index(_, offsetBy:).

var string1 = "www.stackoverflow.com"

var index1 = string1.index(string1.endIndex, offsetBy: -4)

var substring1 = string1.substring(to: index1)

Viele Dinge wurden umbenannt. Die Fälle sind in camelCase geschrieben, startIndexwurden lowerBound.

var string2 = "www.stackoverflow.com"

var index2 = string2.range(of: ".", options: .backwards)?.lowerBound

var substring2 = string2.substring(to: index2!)

Außerdem würde ich nicht empfehlen, das Auspacken zu erzwingen index2. Sie können die optionale Bindung oder verwenden map. Persönlich bevorzuge ich map:

var substring3 = index2.map(string2.substring(to:))

Swift 4

Die Swift 3-Version ist noch gültig, aber jetzt können Sie Indizes mit Indexbereichen verwenden:

let string1 = "www.stackoverflow.com"

let index1 = string1.index(string1.endIndex, offsetBy: -4)

let substring1 = string1[..<index1]

Der zweite Ansatz bleibt unverändert:

let string2 = "www.stackoverflow.com"

let index2 = string2.range(of: ".", options: .backwards)?.lowerBound

let substring3 = index2.map(string2.substring(to:))
fpg1503
quelle
1
Danke @ fpg1503. Dies ist die Art von Antwort, nach der ich gesucht habe. Die anderen Antworten lehrten mich oder erinnerten mich an Merkmale in der Sprache, aber so werde ich mein Problem lösen.
Jason Hocker
1
Die Verwendung von Swift 2.0 string1.endIndex.advancedBy(-4)funktioniert für mich anstelle vonadvance
Alex Koshy
90
Gibt es ernsthaft keine Möglichkeit, dies einfach zu tun?
Devios1
12
@devios alles wahr. Ich bin Swift im Vergleich zu Objective-C dankbar, aber meiner Meinung nach sind die Bedenken, die zu diesem wahnsinnig umständlichen Code führen, für 99% des Codes und der Codierer da draußen irrelevant. Schlimmer noch, wir werden am Ende selbst schlechte Convenience-Erweiterungen schreiben. Wenn reguläre Entwickler diese übergeordneten Probleme nicht verstehen können, können sie MINDESTENS eine Ad-hoc-API schreiben, um die Probleme der Fußgänger zu lösen, mit denen wir Software entwickeln. Die Tendenz zur Konvertierung NSStringist offensichtlich auch schlecht, weil wir alle irgendwann von den Foundation (Legacy) -Klassen weg wollen. Also ... mehr schimpfen!
Dan Rosenstark
2
In Swift 4 können Sie dies tun string1[..<index1]. Keine Notwendigkeit für string1.startIndex.
BauerMusic
26

Swift 3, XCode 8

func lastIndexOfCharacter(_ c: Character) -> Int? {
    return range(of: String(c), options: .backwards)?.lowerBound.encodedOffset
}

Da advancedBy(Int)ist weg, seit Swift 3 die StringMethode verwendet index(String.Index, Int). Schauen Sie sich diese StringErweiterung mit Teilzeichenfolge und Freunden an:

public extension String {

    //right is the first encountered string after left
    func between(_ left: String, _ right: String) -> String? {
        guard let leftRange = range(of: left), let rightRange = range(of: right, options: .backwards)
        , leftRange.upperBound <= rightRange.lowerBound
            else { return nil }

        let sub = self.substring(from: leftRange.upperBound)
        let closestToLeftRange = sub.range(of: right)!
        return sub.substring(to: closestToLeftRange.lowerBound)
    }

    var length: Int {
        get {
            return self.characters.count
        }
    }

    func substring(to : Int) -> String {
        let toIndex = self.index(self.startIndex, offsetBy: to)
        return self.substring(to: toIndex)
    }

    func substring(from : Int) -> String {
        let fromIndex = self.index(self.startIndex, offsetBy: from)
        return self.substring(from: fromIndex)
    }

    func substring(_ r: Range<Int>) -> String {
        let fromIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
        let toIndex = self.index(self.startIndex, offsetBy: r.upperBound)
        return self.substring(with: Range<String.Index>(uncheckedBounds: (lower: fromIndex, upper: toIndex)))
    }

    func character(_ at: Int) -> Character {
        return self[self.index(self.startIndex, offsetBy: at)]
    }

    func lastIndexOfCharacter(_ c: Character) -> Int? {
        guard let index = range(of: String(c), options: .backwards)?.lowerBound else
        { return nil }
        return distance(from: startIndex, to: index)
    }
}

AKTUALISIERTE Erweiterung für Swift 4

public extension String {

    //right is the first encountered string after left
    func between(_ left: String, _ right: String) -> String? {
        guard
            let leftRange = range(of: left), let rightRange = range(of: right, options: .backwards)
            , leftRange.upperBound <= rightRange.lowerBound
            else { return nil }

        let sub = self[leftRange.upperBound...]
        let closestToLeftRange = sub.range(of: right)!            
        return String(sub[..<closestToLeftRange.lowerBound])
    }

    var length: Int {
        get {
            return self.count
        }
    }

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

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

    func substring(_ r: Range<Int>) -> String {
        let fromIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
        let toIndex = self.index(self.startIndex, offsetBy: r.upperBound)
        let indexRange = Range<String.Index>(uncheckedBounds: (lower: fromIndex, upper: toIndex))
        return String(self[indexRange])
    }

    func character(_ at: Int) -> Character {
        return self[self.index(self.startIndex, offsetBy: at)]
    }

    func lastIndexOfCharacter(_ c: Character) -> Int? {
        guard let index = range(of: String(c), options: .backwards)?.lowerBound else
        { return nil }
        return distance(from: startIndex, to: index)
    }
}

Verwendung:

let text = "www.stackoverflow.com"
let at = text.character(3) // .
let range = text.substring(0..<3) // www
let from = text.substring(from: 4) // stackoverflow.com
let to = text.substring(to: 16) // www.stackoverflow
let between = text.between(".", ".") // stackoverflow
let substringToLastIndexOfChar = text.lastIndexOfCharacter(".") // 17

PS Es ist wirklich seltsam, dass Entwickler gezwungen sind, sich damit zu befassen, String.Indexanstatt einfach Int. Warum sollten wir uns um die interne StringMechanik kümmern und nicht nur einfache substring()Methoden haben?

serg_zhd
quelle
Sie sollten encodedOffsetdiesen Kommentar und den richtigen Weg nicht verwenden, um dies zu erreichen. Stackoverflow.com/questions/34540185/…
Leo Dabus
18

Ich würde es mit einem Index ( s[start..<end]) tun :

Swift 3, 4, 5

let s = "www.stackoverflow.com"
let start = s.startIndex
let end = s.index(s.endIndex, offsetBy: -4)
let substring = s[start..<end] // www.stackoverflow
Marián Černý
quelle
11

bearbeiten / aktualisieren:

In Swift 4 oder höher (Xcode 10.0+) können Sie die neue BidirectionalCollection- Methode lastIndex (von :) verwenden.

func lastIndex(of element: Element) -> Int?

let string = "www.stackoverflow.com"
if let lastIndex = string.lastIndex(of: ".") {
    let subString = string[..<lastIndex]  // "www.stackoverflow"
}
Leo Dabus
quelle
Dies ist eine großartige Antwort, aber es scheint, dass diese Eigenschaft mit Swift 2 nach NSUrl verschoben wurde. Vielleicht hilft dies den Leuten, dies in Zukunft zu lesen ...
chuky
8

So mache ich es. Sie können es genauso machen oder diesen Code für Ideen verwenden.

let s = "www.stackoverflow.com"
s.substringWithRange(0..<s.lastIndexOf("."))

Hier sind die Erweiterungen, die ich benutze:

import Foundation
extension String {

  var length: Int {
    get {
      return countElements(self)
    }
  }

  func indexOf(target: String) -> Int {
    var range = self.rangeOfString(target)
    if let range = range {
      return distance(self.startIndex, range.startIndex)
    } else {
      return -1
    }
  }

  func indexOf(target: String, startIndex: Int) -> Int {
    var startRange = advance(self.startIndex, startIndex)        
    var range = self.rangeOfString(target, options: NSStringCompareOptions.LiteralSearch, range: Range<String.Index>(start: startRange, end: self.endIndex))
    if let range = range {
      return distance(self.startIndex, range.startIndex)
    } else {
      return -1
    }
  }

  func lastIndexOf(target: String) -> Int {
    var index = -1
    var stepIndex = self.indexOf(target)
    while stepIndex > -1 {
      index = stepIndex
      if stepIndex + target.length < self.length {
        stepIndex = indexOf(target, startIndex: stepIndex + target.length)
      } else {
        stepIndex = -1
      }
    }
    return index
  } 

  func substringWithRange(range:Range<Int>) -> String {
    let start = advance(self.startIndex, range.startIndex)
    let end = advance(self.startIndex, range.endIndex)
    return self.substringWithRange(start..<end)
  }

}

Credit albertbori / Common Swift String Extensions

Im Allgemeinen bin ich ein starker Befürworter von Erweiterungen, insbesondere für Anforderungen wie String-Manipulation, Suche und Slicing.

joelparkerhenderson
quelle
2
Ich denke, das sollte Apple wirklich tun, um die API von String in Swift zu verbessern.
skyline75489
2
Suche nach dieser API. Apple Swift fehlt eine Menge grundlegender APIs. Es ist eine sehr komplexe Sprache und auch nicht vollständig. Swift ist Bullshit!
Loc
Hier ist eine gegabelte und aktualisierte Swift 3-Version der Bibliothek, auf die Sie verweisen: github.com/iamjono/SwiftString
RenniePet
5

String hat eingebaute Teilzeichenfolge-Funktion:

extension String : Sliceable {
    subscript (subRange: Range<String.Index>) -> String { get }
}

Wenn Sie "zum ersten Index eines Zeichens gehen" möchten , können Sie die Teilzeichenfolge mithilfe der integrierten find()Funktion abrufen :

var str = "www.stackexchange.com"
str[str.startIndex ..< find(str, ".")!] // -> "www"

Um den letzten Index zu finden , können wir implementieren findLast().

/// Returns the last index where `value` appears in `domain` or `nil` if
/// `value` is not found.
///
/// Complexity: O(\ `countElements(domain)`\ )
func findLast<C: CollectionType where C.Generator.Element: Equatable>(domain: C, value: C.Generator.Element) -> C.Index? {
    var last:C.Index? = nil
    for i in domain.startIndex..<domain.endIndex {
        if domain[i] == value {
            last = i
        }
    }
    return last
}

let str = "www.stackexchange.com"
let substring = map(findLast(str, ".")) { str[str.startIndex ..< $0] } // as String?
// if "." is found, substring has some, otherwise `nil`

HINZUGEFÜGT:

Vielleicht ist eine BidirectionalIndexTypespezielle Version von findLastschneller:

func findLast<C: CollectionType where C.Generator.Element: Equatable, C.Index: BidirectionalIndexType>(domain: C, value: C.Generator.Element) -> C.Index? {
    for i in lazy(domain.startIndex ..< domain.endIndex).reverse() {
        if domain[i] == value {
            return i
        }
    }
    return nil
}
Rintaro
quelle
Der Index für String scheint in Swift 2.0 nicht verfügbar zu sein. Kennen Sie einen Ersatz?
Cory
Wissen Sie, wie ich den Index in Swift 4 oder höher auf BidirectionalIndexType beschränken kann?
Leo Dabus
5

Sie können diese Erweiterungen verwenden:

Swift 2.3

 extension String
    {
        func substringFromIndex(index: Int) -> String
        {
            if (index < 0 || index > self.characters.count)
            {
                print("index \(index) out of bounds")
                return ""
            }
            return self.substringFromIndex(self.startIndex.advancedBy(index))
        }

        func substringToIndex(index: Int) -> String
        {
            if (index < 0 || index > self.characters.count)
            {
                print("index \(index) out of bounds")
                return ""
            }
            return self.substringToIndex(self.startIndex.advancedBy(index))
        }

        func substringWithRange(start: Int, end: Int) -> String
        {
            if (start < 0 || start > self.characters.count)
            {
                print("start index \(start) out of bounds")
                return ""
            }
            else if end < 0 || end > self.characters.count
            {
                print("end index \(end) out of bounds")
                return ""
            }
            let range = Range(start: self.startIndex.advancedBy(start), end: self.startIndex.advancedBy(end))
            return self.substringWithRange(range)
        }

        func substringWithRange(start: Int, location: Int) -> String
        {
            if (start < 0 || start > self.characters.count)
            {
                print("start index \(start) out of bounds")
                return ""
            }
            else if location < 0 || start + location > self.characters.count
            {
                print("end index \(start + location) out of bounds")
                return ""
            }
            let range = Range(start: self.startIndex.advancedBy(start), end: self.startIndex.advancedBy(start + location))
            return self.substringWithRange(range)
        }
    }

Swift 3

extension String
{   
    func substring(from index: Int) -> String
    {
        if (index < 0 || index > self.characters.count)
        {
            print("index \(index) out of bounds")
            return ""
        }
        return self.substring(from: self.characters.index(self.startIndex, offsetBy: index))
    }

    func substring(to index: Int) -> String
    {
        if (index < 0 || index > self.characters.count)
        {
            print("index \(index) out of bounds")
            return ""
        }
        return self.substring(to: self.characters.index(self.startIndex, offsetBy: index))
    }

    func substring(start: Int, end: Int) -> String
    {
        if (start < 0 || start > self.characters.count)
        {
            print("start index \(start) out of bounds")
            return ""
        }
        else if end < 0 || end > self.characters.count
        {
            print("end index \(end) out of bounds")
            return ""
        }
        let startIndex = self.characters.index(self.startIndex, offsetBy: start)
        let endIndex = self.characters.index(self.startIndex, offsetBy: end)
        let range = startIndex..<endIndex

        return self.substring(with: range)
    }

    func substring(start: Int, location: Int) -> String
    {
        if (start < 0 || start > self.characters.count)
        {
            print("start index \(start) out of bounds")
            return ""
        }
        else if location < 0 || start + location > self.characters.count
        {
            print("end index \(start + location) out of bounds")
            return ""
        }
        let startIndex = self.characters.index(self.startIndex, offsetBy: start)
        let endIndex = self.characters.index(self.startIndex, offsetBy: start + location)
        let range = startIndex..<endIndex

        return self.substring(with: range)
    }
}

Verwendung:

let string = "www.stackoverflow.com"        
let substring = string.substringToIndex(string.characters.count-4)
ChikabuZ
quelle
5

Swift 4:

extension String {

    /// the length of the string
    var length: Int {
        return self.characters.count
    }

    /// Get substring, e.g. "ABCDE".substring(index: 2, length: 3) -> "CDE"
    ///
    /// - parameter index:  the start index
    /// - parameter length: the length of the substring
    ///
    /// - returns: the substring
    public func substring(index: Int, length: Int) -> String {
        if self.length <= index {
            return ""
        }
        let leftIndex = self.index(self.startIndex, offsetBy: index)
        if self.length <= index + length {
            return self.substring(from: leftIndex)
        }
        let rightIndex = self.index(self.endIndex, offsetBy: -(self.length - index - length))
        return self.substring(with: leftIndex..<rightIndex)
    }

    /// Get substring, e.g. -> "ABCDE".substring(left: 0, right: 2) -> "ABC"
    ///
    /// - parameter left:  the start index
    /// - parameter right: the end index
    ///
    /// - returns: the substring
    public func substring(left: Int, right: Int) -> String {
        if length <= left {
            return ""
        }
        let leftIndex = self.index(self.startIndex, offsetBy: left)
        if length <= right {
            return self.substring(from: leftIndex)
        }
        else {
            let rightIndex = self.index(self.endIndex, offsetBy: -self.length + right + 1)
            return self.substring(with: leftIndex..<rightIndex)
        }
    }
}

Sie können es wie folgt testen:

    print("test: " + String("ABCDE".substring(index: 2, length: 3) == "CDE"))
    print("test: " + String("ABCDE".substring(index: 0, length: 3) == "ABC"))
    print("test: " + String("ABCDE".substring(index: 2, length: 1000) == "CDE"))
    print("test: " + String("ABCDE".substring(left: 0, right: 2) == "ABC"))
    print("test: " + String("ABCDE".substring(left: 1, right: 3) == "BCD"))
    print("test: " + String("ABCDE".substring(left: 3, right: 1000) == "DE"))

Überprüfen Sie die Bibliothek https://gitlab.com/seriyvolk83/SwiftEx . Es enthält diese und andere hilfreiche Methoden.

Alexander Volkov
quelle
4

Möchten Sie eine Teilzeichenfolge einer Zeichenfolge vom Startindex bis zum letzten Index eines ihrer Zeichen abrufen? In diesem Fall können Sie eine der folgenden Swift 2.0+ Methoden auswählen.

Methoden, die erfordern Foundation

Holen Sie sich eine Teilzeichenfolge, die den letzten Index eines Zeichens enthält:

import Foundation

let string = "www.stackoverflow.com"
if let rangeOfIndex = string.rangeOfCharacterFromSet(NSCharacterSet(charactersInString: "."), options: .BackwardsSearch) {
    print(string.substringToIndex(rangeOfIndex.endIndex))
}

// prints "www.stackoverflow."

Holen Sie sich einen Teilstring, der NICHT den letzten Index eines Zeichens enthält:

import Foundation

let string = "www.stackoverflow.com"
if let rangeOfIndex = string.rangeOfCharacterFromSet(NSCharacterSet(charactersInString: "."), options: .BackwardsSearch) {
    print(string.substringToIndex(rangeOfIndex.startIndex))
}

// prints "www.stackoverflow"

Wenn Sie diese Vorgänge wiederholen müssen, Stringkann eine Erweiterung eine gute Lösung sein:

import Foundation

extension String {
    func substringWithLastInstanceOf(character: Character) -> String? {
        if let rangeOfIndex = rangeOfCharacterFromSet(NSCharacterSet(charactersInString: String(character)), options: .BackwardsSearch) {
            return self.substringToIndex(rangeOfIndex.endIndex)
        }
        return nil
    }
    func substringWithoutLastInstanceOf(character: Character) -> String? {
        if let rangeOfIndex = rangeOfCharacterFromSet(NSCharacterSet(charactersInString: String(character)), options: .BackwardsSearch) {
            return self.substringToIndex(rangeOfIndex.startIndex)
        }
        return nil
    }
}

print("www.stackoverflow.com".substringWithLastInstanceOf("."))
print("www.stackoverflow.com".substringWithoutLastInstanceOf("."))

/*
prints:
Optional("www.stackoverflow.")
Optional("www.stackoverflow")
*/

Methoden, die NICHT erforderlich sind Foundation

Holen Sie sich eine Teilzeichenfolge, die den letzten Index eines Zeichens enthält:

let string = "www.stackoverflow.com"
if let reverseIndex = string.characters.reverse().indexOf(".") {
    print(string[string.startIndex ..< reverseIndex.base])
}

// prints "www.stackoverflow."

Holen Sie sich einen Teilstring, der NICHT den letzten Index eines Zeichens enthält:

let string = "www.stackoverflow.com"
if let reverseIndex = string.characters.reverse().indexOf(".") {
    print(string[string.startIndex ..< reverseIndex.base.advancedBy(-1)])
}

// prints "www.stackoverflow"

Wenn Sie diese Vorgänge wiederholen müssen, Stringkann eine Erweiterung eine gute Lösung sein:

extension String {
    func substringWithLastInstanceOf(character: Character) -> String? {
        if let reverseIndex = characters.reverse().indexOf(".") {
            return self[self.startIndex ..< reverseIndex.base]
        }
        return nil
    }
    func substringWithoutLastInstanceOf(character: Character) -> String? {
        if let reverseIndex = characters.reverse().indexOf(".") {
            return self[self.startIndex ..< reverseIndex.base.advancedBy(-1)]
        }
        return nil
    }
}

print("www.stackoverflow.com".substringWithLastInstanceOf("."))
print("www.stackoverflow.com".substringWithoutLastInstanceOf("."))

/*
prints:
Optional("www.stackoverflow.")
Optional("www.stackoverflow")
*/
Imanou Petit
quelle
4

Hier ist eine einfache und kurze Möglichkeit, einen Teilstring zu erhalten, wenn Sie den Index kennen:

let s = "www.stackoverflow.com"
let result = String(s.characters.prefix(17)) // "www.stackoverflow"

Die App stürzt nicht ab, wenn Ihr Index die Länge der Zeichenfolge überschreitet:

let s = "short"
let result = String(s.characters.prefix(17)) // "short"

Beide Beispiele sind Swift 3-fähig .

Andrey Gordeev
quelle
4

Das einzige, was Klappern hinzufügt, ist das wiederholte stringVar :

stringVar [ stringVar .index ( stringVar .startIndex, offsetBy: ...)

In Swift 4

Eine Erweiterung kann einige davon reduzieren:

extension String {

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

Dann Verwendung:

let string = "abcde"

let to = string[..<string.index(at: 3)] // abc
let from = string[string.index(at: 3)...] // de

Es ist zu beachten, dass tound fromTyp Substring(oder String.SubSequance) sind. Sie weisen keine neuen Zeichenfolgen zu und sind für die Verarbeitung effizienter.

Um einen StringTyp zurückzubekommen, Substringmuss Folgendes zurückgesetzt werden String:

let backToString = String(from)

Hier wird schließlich eine Zeichenfolge zugewiesen.

bauerMusic
quelle
3
func substr(myString: String, start: Int, clen: Int)->String

{
  var index2 = string1.startIndex.advancedBy(start)
  var substring2 = string1.substringFromIndex(index2)
  var index1 = substring2.startIndex.advancedBy(clen)
  var substring1 = substring2.substringToIndex(index1)

  return substring1   
}

substr(string1, start: 3, clen: 5)
Professor Oak
quelle
3

Swift 3

let string = "www.stackoverflow.com"
let first3Characters = String(string.characters.prefix(3)) // www
let lastCharacters = string.characters.dropFirst(4) // stackoverflow.com (it would be a collection)

//or by index 
let indexOfFouthCharacter = olNumber.index(olNumber.startIndex, offsetBy: 4)
let first3Characters = olNumber.substring(to: indexOfFouthCharacter) // www
let lastCharacters = olNumber.substring(from: indexOfFouthCharacter) // .stackoverflow.com

Guter Artikel zum Verständnis, warum brauchen wir das?

Nik Kov
quelle
2

Ich habe String um zwei Teilstring-Methoden erweitert. Sie können Teilzeichenfolgen mit einem Bereich von / bis oder von / Länge wie folgt aufrufen:

var bcd = "abcdef".substring(1,to:3)
var cde = "abcdef".substring(2,to:-2)
var cde = "abcdef".substring(2,length:3)

extension String {
  public func substring(from:Int = 0, var to:Int = -1) -> String {
    if to < 0 {
        to = self.length + to
    }
    return self.substringWithRange(Range<String.Index>(
        start:self.startIndex.advancedBy(from),
        end:self.startIndex.advancedBy(to+1)))
  }
  public func substring(from:Int = 0, length:Int) -> String {
    return self.substringWithRange(Range<String.Index>(
        start:self.startIndex.advancedBy(from),
        end:self.startIndex.advancedBy(from+length)))
  }
}
andrewz
quelle
self.length ist nicht mehr verfügbar. Sie müssen dies in der Erweiterung hinzufügen (Andrewz, bitte aktualisieren Sie den Code; ich möchte keine weitere Antwort veröffentlichen): public func length () -> Int {return self.lengthOfBytesUsingEncoding (NSUTF16StringEncoding)}
philippe
1

Swift 2.0 Der folgende Code wurde auf XCode 7.2 getestet. Bitte beachten Sie den beigefügten Screenshot unten

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var mainText = "http://stackoverflow.com"

        var range = Range(start: mainText.startIndex.advancedBy(7), end: mainText.startIndex.advancedBy(24))
        var subText = mainText.substringWithRange(range)


        //OR Else use below for LAST INDEX

        range = Range(start: mainText.startIndex.advancedBy(7), end: mainText.endIndex)
        subText = mainText.substringWithRange(range)
    }
}
Chamath Jeevan
quelle
1

In Swift 5

Wir benötigen String.Indexanstelle eines einfachen Int-Werts den Index.

Denken Sie auch daran, wenn wir versuchen, SubString von Swift String( Werttyp ) abzurufen , müssen wir tatsächlich mit dem SequenceProtokoll iterieren , das den String.SubSequenceTyp anstelle von zurückgibtString Typs .

Zurück zu bekommen String aus String.SubSequence, VerwendungString(subString)

Beispiel wie folgt:

    let string = "https://stackoverflow.com"
    let firstIndex = String.Index(utf16Offset: 0, in: string)
    let lastIndex = String.Index(utf16Offset: 6, in: string)
    let subString = String(string[firstIndex...lastIndex])
Macpandit
quelle
0

Für Swift 2.0 ist es so:

var string1 = "www.stackoverflow.com"
var index1 = string1.endIndex.advancedBy(-4)
var substring1 = string1.substringToIndex(index1)
mike.tihonchik
quelle
Vielleicht haben sie es geändert, aber es ist 'advancedBy' (beachten Sie das 'd' am Ende von 'advanced')
Wedge Martin
0

Ich habe den Beitrag von andrewz geändert, um ihn mit Swift 2.0 (und möglicherweise Swift 3.0) kompatibel zu machen. Meiner bescheidenen Meinung nach ist diese Erweiterung leichter zu verstehen und ähnelt dem, was in anderen Sprachen (wie PHP) verfügbar ist .

extension String {

    func length() -> Int {
        return self.lengthOfBytesUsingEncoding(NSUTF16StringEncoding)
    }
    func substring(from:Int = 0, to:Int = -1) -> String {
       var nto=to
        if nto < 0 {
            nto = self.length() + nto
        }
        return self.substringWithRange(Range<String.Index>(
           start:self.startIndex.advancedBy(from),
           end:self.startIndex.advancedBy(nto+1)))
    }
    func substring(from:Int = 0, length:Int) -> String {
        return self.substringWithRange(Range<String.Index>(
            start:self.startIndex.advancedBy(from),
            end:self.startIndex.advancedBy(from+length)))
    }
}
philippe
quelle
0

Ich baue auch eine einfache String-Erweiterung für Swift 4:

extension String {
    func subStr(s: Int, l: Int) -> String { //s=start, l=lenth
        let r = Range(NSRange(location: s, length: l))!
        let fromIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
        let toIndex = self.index(self.startIndex, offsetBy: r.upperBound)
        let indexRange = Range<String.Index>(uncheckedBounds: (lower: fromIndex, upper: toIndex))

        return String(self[indexRange])
     }
}

Sie können es also einfach so nennen:

"Hallo world".subStr(s: 1, l: 3) //prints --> "all"
Marco Weber
quelle
0

Versuchen Sie diese Int-basedProblemumgehung:

extension String {
    // start and end is included
    func intBasedSubstring(_ start: Int, _ end: Int) -> String {
        let endOffset: Int = -(count - end - 1)
        let startIdx = self.index(startIndex, offsetBy: start)
        let endIdx = self.index(endIndex, offsetBy: endOffset)
        return String(self[startIdx..<endIdx])
    }
}

Hinweis: Es ist nur eine Übung. Es überprüft nicht die Grenze. An Ihre Bedürfnisse anpassen.

Steveluoxin
quelle
-1

Hier ist eine einfache Möglichkeit, Teilzeichenfolgen in Swift abzurufen

import UIKit

var str = "Hello, playground" 
var res = NSString(string: str)
print(res.substring(from: 4))
print(res.substring(to: 10))
ZagorTeNej
quelle
OP fragt "Wie man Teilzeichenfolgen vom Anfang bis zum letzten Zeichenindex erhält" und nicht, wie Teilzeichenfolgen mit vordefinierten fest codierten Werten abgerufen werden.
Eric Aya
Dies war das ursprüngliche Beispiel: Konvertieren Sie "www.stackoverflow.com" in "www.stackoverflow". Wenn Sie einen Teilstring vom Anfang bis zum Ende wünschen, gibt es nichts zu tun, dh das Ergebnis ist eine Eingabezeichenfolge wie sie ist. Bitte stellen Sie die Nützlichkeit der obigen Antwort wieder her.
ZagorTeNej