Swift: как получить подстроку от начала до последнего индекса символа


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

Никаких расширений, чистый идиоматический Swift

Swift 2.0

advanceтеперь является частью Indexи называется advancedBy. Вам это нравится:

var string1 = "www.stackoverflow.com"

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

var substring1 = string1.substringToIndex(index1)

Swift 3.0

Вы не можете вызвать advancedBya, 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:))

Swift 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
У string1.endIndex.advancedBy(-4)меня работает Swift 2.0 вместоadvance
Alex Koshy

92
Неужели нет возможности сделать это просто?
devios1

12
@devios все правда. Я благодарен за Swift по сравнению с Objective-C, но IMHO проблемы, которые приводят к этому безумно неудобному коду, не имеют отношения к 99% кода и кодеров. Хуже того, мы сами напишем плохие расширения для удобства. Если обычные разработчики не могут понять эти высокоуровневые проблемы, они НАИМЕНЕЕ могут написать специальный API для решения простых проблем, с которыми мы создаем программное обеспечение. Тенденция к преобразованию в NSStringявно плохая, потому что в конечном итоге мы все хотим уйти от классов Foundation (устаревших). Так что .... больше разглагольствования!
Дэн Розенстарк

2
В Swift 4 это возможно string1[..<index1]. Нет необходимости в string1.startIndex.
bauerMusic

26

Swift 3, XCode 8

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

Поскольку метод advancedBy(Int)использования Swift 3 отсутствует . Посмотрите это расширение с подстрокой и друзьями:Stringindex(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/…
Лео Дабус,

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 (of :)

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. Может быть, это поможет людям читать это в будущем ...
chuky

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

}

Кредит albertbori / Common Swift String Extensions

Как правило, я убежденный сторонник расширений, особенно для таких нужд, как манипуляции со строками, поиск и нарезка.


2
Я думаю, что это действительно то, что Apple должна сделать, чтобы улучшить API String в Swift.
skyline75489

2
Ищу этот API. Apple Swift не хватает большого количества базового API. Это очень сложный и неполный язык. Свифт - чушь собачья!
Loc

Вот разветвленная и обновленная до 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, вы знаете замену?
Кори

Знаете ли вы, как я могу ограничить индекс до BidirectionalIndexType в Swift 4 или новее?
Лео Дабус

5

Вы можете использовать эти расширения:

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

Использование:

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

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

вы можете проверить это следующим образом:

    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 . Он содержит эти и другие полезные методы.


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

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

Хорошая статья для понимания, зачем нам это


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 больше не доступен. Вам нужно добавить это в расширение (Эндрюз, пожалуйста, обновите код; я не хочу публиковать другой ответ): 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 для представления индекса.

Также помните, что когда мы пытаемся получить подстроку из 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)

Возможно, они его изменили, но это «advancedBy» (обратите внимание на букву «d» в конце слова «advanced»)
Wedge Martin

0

Я изменил сообщение Эндрюза, чтобы сделать его совместимым со 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))

OP спрашивает: «Как получить подстроку от начала до последнего индекса символа», а не как получить подстроку с использованием предопределенных жестко заданных значений.
Эрик Айя

Это был оригинальный пример: преобразовать «www.stackoverflow.com» в «www.stackoverflow». Если вам нужна подстрока от начала до конца, то делать нечего, т.е. результат будет входной строкой как есть. Пожалуйста, восстановите полезность приведенного выше ответа.
ZagorTeNej
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.