Swift: How to get substring from start to last index of character

前端 未结 22 733
感情败类
感情败类 2020-11-30 19:09

I want to learn the best/simplest way to turn a string into another string but with only a subset, starting at the beginning and going to the last index of a character.

相关标签:
22条回答
  • 2020-11-30 19:43
    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)
    
    0 讨论(0)
  • 2020-11-30 19:43

    In Swift 5

    We need String.Index instead of simple Int value to represent Index.

    Also remember, when we try to get subString from Swift String (value type), we actually have to iterate with Sequence protocol, which returns String.SubSequence type instead of String type.

    To get back String from String.SubSequence, use String(subString)

    Example As Below:

        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])
    
    0 讨论(0)
  • 2020-11-30 19:44

    Swift 3, XCode 8

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

    Since advancedBy(Int) is gone since Swift 3 use String's method index(String.Index, Int). Check out this String extension with substring and friends:

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

    UPDATED extension for 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)
        }
    }
    

    Usage:

    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
    

    P.S. It's really odd that developers forced to deal with String.Index instead of plain Int. Why should we bother about internal String mechanics and not just have simple substring() methods?

    0 讨论(0)
  • 2020-11-30 19:44

    Here is a simple way to get substring in Swift

    import UIKit
    
    var str = "Hello, playground" 
    var res = NSString(string: str)
    print(res.substring(from: 4))
    print(res.substring(to: 10))
    
    0 讨论(0)
  • 2020-11-30 19:46

    You can use these extensions:

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

    Usage:

    let string = "www.stackoverflow.com"        
    let substring = string.substringToIndex(string.characters.count-4)
    
    0 讨论(0)
  • 2020-11-30 19:48

    Here's an easy and short way to get a substring if you know the index:

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

    It won't crash the app if your index exceeds string's length:

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

    Both examples are Swift 3 ready.

    0 讨论(0)
提交回复
热议问题