Швидкий: Як отримати підрядку від початку до останнього індексу символів


110

Я хочу дізнатися найкращий / найпростіший спосіб перетворити рядок в інший рядок, але лише з підмножиною, починаючи з початку і переходячи до останнього індексу символу.

Наприклад, перетворіть "www.stackoverflow.com" у "www.stackoverflow". Який фрагмент коду зробив би це і був найбільш швидким? (Я сподіваюся, що це не викликає дебатів, але я не можу знайти хороший урок, як поводитися з підрядками в Swift.

Відповіді:


202

Просто доступ назад

Найкращим способом є використання substringToIndexкомбінованого до endIndexвластивості та advanceглобальної функції.

var string1 = "www.stackoverflow.com"

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

var substring1 = string1.substringToIndex(index1)

Шукаєте рядок, починаючи зі зворотного боку

Використовуйте rangeOfStringта встановіть optionsна.BackwardsSearch

var string2 = "www.stackoverflow.com"

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

var substring2 = string2.substringToIndex(index2!)

Ніяких розширень, чисто ідіоматичний Свіфт

Швидкий 2.0

advanceзараз є частиною Indexі називається advancedBy. Ви робите це так:

var string1 = "www.stackoverflow.com"

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

var substring1 = string1.substringToIndex(index1)

Swift 3.0

Ви не можете зателефонувати advancedByна, Stringоскільки він містить елементи змінного розміру Ви повинні використовувати index(_, offsetBy:).

var string1 = "www.stackoverflow.com"

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

var substring1 = string1.substring(to: index1)

Багато речей було перейменовано. Справи написані camelCase, startIndexстав lowerBound.

var string2 = "www.stackoverflow.com"

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

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

Також я б не рекомендував примусово розкручувати index2. Можна використовувати необов'язкове зв'язування або map. Особисто я вважаю за краще використовувати map:

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

Швидкий 4

Версія Swift 3 досі діє, але тепер ви можете використовувати підписки з діапазонами індексів:

let string1 = "www.stackoverflow.com"

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

let substring1 = string1[..<index1]

Другий підхід залишається незмінним:

let string2 = "www.stackoverflow.com"

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

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

1
Дякуємо @ fpg1503 Це така відповідь, яку я шукав. Інші відповіді мене навчали або нагадували про особливості мови, але саме так я буду використовувати для вирішення своєї проблеми.
Джейсон Хокер

1
Використовуючи Swift 2.0, string1.endIndex.advancedBy(-4)працює замість менеadvance
Алекс Коші

92
Невже серйозно немає способу зробити це просто?
devios1

12
@devios все правда. Я вдячний за Swift порівняно з Objective-C, але IMHO занепокоєння, які призводять до цього шалено незручного коду, не має значення для 99% коду та кодерів. Гірше, що ми в остаточному підсумку самі пишемо розширення зручності. Якщо звичайні розробники не можуть зрозуміти ці проблеми вищого рівня, вони ЛИШЕ зможуть написати спеціальний API для вирішення проблем пішоходів, з якими ми розробляємо програмне забезпечення. Тенденція до перетворення NSStringтеж очевидно погана, оскільки врешті-решт ми всі хочемо відійти від класів Фонду (спадщини). Отже .... більше рейтинг!
Дан Розенстарк

2
У Swift 4 ви можете це зробити string1[..<index1]. Не потрібно string1.startIndex.
bauerMusic

26

Швидкий 3, XCode 8

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

Так як advancedBy(Int)пішов , так як Swift 3 використання Stringметоду «s index(String.Index, Int). Ознайомтеся з цим Stringрозширенням із підрядками та друзями:

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

ОНОВЛЕННЕ розширення для 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)
    }
}

Використання:

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 Насправді дивно, що розробники змушені мати справу, String.Indexа не просто Int. Чому ми повинні турбуватися про внутрішню Stringмеханіку, а не просто прості substring()методи?


Ви не повинні використовувати encodedOffsetперевірити цей коментар і правильний шлях для досягнення цієї stackoverflow.com/questions/34540185 / ...
Лео Dabus

18

Я б це зробив, використовуючи індекс ( s[start..<end]):

Швидкий 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

11

редагування / оновлення:

В Swift 4 або пізнішої версії (Xcode 10.0+) , ви можете використовувати новий BidirectionalCollection метод LastIndex (з :)

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

let string = "www.stackoverflow.com"
if let lastIndex = string.lastIndex(of: ".") {
    let subString = string[..<lastIndex]  // "www.stackoverflow"
}

Це чудова відповідь, але, схоже, що за допомогою Swift 2 ця властивість була перенесена в NSUrl. Можливо, це допомагає людям читати це в майбутньому ...
Чак

8

Ось як я це роблю. Ви можете це зробити так само або використовувати цей код для ідей.

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

Ось розширення, які я використовую:

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 / Загальні розширення стрімких рядків

Як правило, я є прихильником розширень, особливо для таких потреб, як обробка струн, пошук та нарізка.


2
Я думаю, що це дійсно те, що Apple повинна зробити, щоб поліпшити API String in Swift.
skyline75489

2
Шукаєте цей API. Apple Swift не вистачає багато базового API. Це дуже складна мова, а також неповна. Швидкий - фігня!
Лок

Ось роздвоєна та оновлена ​​версія Swift 3 бібліотеки, на яку ви посилаєтеся: github.com/iamjono/SwiftString
RenniePet

5

String має вбудовану функцію підрядки:

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

Якщо ви хочете "перейти до першого індексу символу", ви можете отримати підрядку за допомогою вбудованої find()функції:

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

Щоб знайти останній індекс, ми можемо реалізувати 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`

ДОДАТО:

Можливо, BidirectionalIndexTypeспеціалізована версія findLastшвидше:

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
}

Здається, що підписка для String не доступна в Swift 2.0, чи знаєте ви заміну?
Cory

Чи знаєте ви, як я можу обмежувати індекс BidirectionalIndexType в Swift 4 або пізніших версіях?
Лев Дабус

5

Ви можете використовувати ці розширення:

Швидкий 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)
        }
    }

Швидкий 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)
    }
}

Використання:

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

5

Швидкий 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)
        }
    }
}

ви можете перевірити його наступним чином:

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

Перевірте https://gitlab.com/seriyvolk83/SwiftEx library. Він містить ці та інші корисні методи.


4

Ви хочете отримати підрядку рядка від початкового індексу до останнього індексу одного з його символів? Якщо так, ви можете обрати один із наступних методів Swift 2.0+.

Методи, які вимагають Foundation

Отримайте підрядку, що включає останній індекс символу:

import Foundation

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

// prints "www.stackoverflow."

Отримайте підрядку, яка НЕ ​​включає останній індекс символу:

import Foundation

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

// prints "www.stackoverflow"

Якщо вам потрібно повторити ці операції, розширення Stringможе бути хорошим рішенням:

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")
*/

Методи, які НЕ вимагають Foundation

Отримайте підрядку, що включає останній індекс символу:

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

// prints "www.stackoverflow."

Отримайте підрядку, яка НЕ ​​включає останній індекс символу:

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

// prints "www.stackoverflow"

Якщо вам потрібно повторити ці операції, розширення Stringможе бути хорошим рішенням:

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")
*/

4

Ось простий і короткий спосіб отримати підрядку, якщо ви знаєте індекс:

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

Він не завершить роботу програми, якщо ваш індекс перевищує довжину рядка:

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

Обидва приклади готові Swift 3 .


4

Єдине, що додає клаттер - це повторення stringVar:

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

У Swift 4

Розширення може зменшити щось із цього:

extension String {

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

Потім, використання:

let string = "abcde"

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

Слід зазначити, що toі fromє типом Substring(або String.SubSequance). Вони не виділяють нових рядків і є більш ефективними для обробки.

Щоб повернути Stringтип, Substringпотрібно повернути його до String:

let backToString = String(from)

Саме тут нарешті виділяється рядок.


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)

3

Швидкий 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

Гарна стаття для розуміння, навіщо нам це потрібно


2

Я розширив String двома методами підрядки. Ви можете викликати підрядку з / в діапазон або з / довжини так:

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

self.length більше не доступний. Вам потрібно додати це в розширення (Andrewz, оновіть код; я не хочу публікувати іншу відповідь): public func length () -> Int {return self.lengthOfBytesUsingEncoding (NSUTF16StringEncoding)}
philippe

1

Swift 2.0 Код нижче тестується на XCode 7.2. Перегляньте доданий знімок екрана внизу

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

1

У Swift 5

Нам потрібно String.Indexзамість простого значення Int представити індекс.

Пам'ятайте також, що коли ми намагаємося отримати subString від Swift String(тип значення), ми насправді мусимо повторити Sequenceпротокол, який повертає String.SubSequenceтип замість Stringтипу.

Щоб повернутися Stringз String.SubSequence, використовуйтеString(subString)

Приклад нижче:

    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

Для Swift 2.0 це так:

var string1 = "www.stackoverflow.com"
var index1 = string1.endIndex.advancedBy(-4)
var substring1 = string1.substringToIndex(index1)

Можливо, вони змінили його, але це "просунутий" (зверніть увагу на "d" в кінці "просунутого")
Клін Мартін,

0

Я змінив допис andrewz, щоб зробити його сумісним із Swift 2.0 (і, можливо, Swift 3.0). На мою скромну думку, це розширення легше зрозуміти і схоже на те, що є в інших мовах (наприклад, PHP).

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

0

Я також будую просте розширення String для 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])
     }
}

Тож ви можете легко назвати це так:

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

0

Спробуйте це Int-basedвирішити:

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

Примітка. Це просто практика. Це не перевіряє межу. Змініть відповідно до ваших потреб.


-1

Ось простий спосіб отримати підрядку в Swift

import UIKit

var str = "Hello, playground" 
var res = NSString(string: str)
print(res.substring(from: 4))
print(res.substring(to: 10))

ОП запитує "Як отримати підрядку від початку до останнього індексу символів", а не як отримати підрядку за допомогою заздалегідь заданих твердо кодованих значень.
Ерік Айя

Це був оригінальний приклад: конвертувати "www.stackoverflow.com" у "www.stackoverflow". Якщо ви хочете підстрочку від початку до кінця, то нічого робити, тобто результат - це рядок введення, як є. Відновіть корисність наведеної вище відповіді.
ZagorTeNej
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.