Как я могу использовать подписки нарезки строк в Swift 4?

294

У меня есть следующий простой код, написанный на Swift 3:

let str = "Hello, playground"
let index = str.index(of: ",")!
let newStr = str.substring(to: index)

Из Xcode 9 beta 5 я получаю следующее предупреждение:

« substring(to:)» устарело: используйте Stringподстрочный индекс с оператором «частичный диапазон от».

Как можно использовать этот индекс среза с частичным диапазоном из Swift 4?

Адриан
источник
var str = "Привет, детская площадка" let indexcut = str.firstIndex (of: ",") print (String (str [.. <indexcut!])) print (String (str [indexcut! ...]))
user1828845

Ответы:

375

Вы должны оставить одну сторону пустой , отсюда и название «частичный диапазон».

let newStr = str[..<index]

То же самое относится к частичному диапазону от операторов, просто оставьте другую сторону пустой:

let newStr = str[index...]

Имейте в виду, что эти операторы диапазона возвращают a Substring. Если вы хотите преобразовать его в строку, используйте Stringфункцию инициализации:

let newStr = String(str[..<index])

Вы можете прочитать больше о новых подстроках здесь .

Тамас Сенгель
источник
8
str[..<index]возвращает Substring. Если вы хотите newStrбыть, Stringвы должны написать:let newStr = "\(str[..<index])"
Линдеманн
12
Используя интерполяцию строки с одиночкой Substring, вероятно , немного запутанным, так как то , что вы на самом деле пытаетесь достичь является Stringинициализация: let newStr = String(str[..<index]).
Гэри
5
Обновление кода, где моим значением index было просто целое число, выдает сообщение об ошибке Cannot subscript a value of type 'String' with an index of type 'PartialRangeUpTo<Int>'. Какие типы значений должны использоваться там?
ConfusionTowers
22
@ConfusionTowers, строковые индексы Swift не являются целыми числами , и это не изменилось в версии 4. Возможно, вам понадобится str[..<str.index(str.startIndex, offsetBy: 8)]что-то в этом роде. Имейте в виду, что str.indexэто линейная операция времени в функции offsetBy.
zneak
6
@zneak Вы, вероятно, хотитеstr.prefix(8)
Тим Vermeulen
264

Преобразовать подстроку (Swift 3) в нарезку строк (Swift 4)

Примеры в Swift 3, 4:

let newStr = str.substring(to: index) // Swift 3
let newStr = String(str[..<index]) // Swift 4

let newStr = str.substring(from: index) // Swift 3
let newStr = String(str[index...]) // Swift 4 

let range = firstIndex..<secondIndex // If you have a range
let newStr = = str.substring(with: range) // Swift 3
let newStr = String(str[range])  // Swift 4
Мохаммад Садег Панадгу
источник
5
Perfecto, и спасибо за то, что вы дали 3 и 4 примера рядом, облегчает обновление моего проекта!
Итан Паркер
86

Свифт 5, 4

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

let text = "Hello world"
text[0] // H
text[...3] // "Hell"
text[6..<text.count] // world
text[NSRange(location: 6, length: 3)] // wor

Код

import Foundation

public extension String {
  subscript(value: Int) -> Character {
    self[index(at: value)]
  }
}

public extension String {
  subscript(value: NSRange) -> Substring {
    self[value.lowerBound..<value.upperBound]
  }
}

public extension String {
  subscript(value: CountableClosedRange<Int>) -> Substring {
    self[index(at: value.lowerBound)...index(at: value.upperBound)]
  }

  subscript(value: CountableRange<Int>) -> Substring {
    self[index(at: value.lowerBound)..<index(at: value.upperBound)]
  }

  subscript(value: PartialRangeUpTo<Int>) -> Substring {
    self[..<index(at: value.upperBound)]
  }

  subscript(value: PartialRangeThrough<Int>) -> Substring {
    self[...index(at: value.upperBound)]
  }

  subscript(value: PartialRangeFrom<Int>) -> Substring {
    self[index(at: value.lowerBound)...]
  }
}

private extension String {
  func index(at offset: Int) -> String.Index {
    index(startIndex, offsetBy: offset)
  }
}
dimpiax
источник
14
эта функциональность должна быть быстрым по умолчанию.
Лаймис
4
Определенно
пиарите
2
Это исправление самой уродливой части Swift.
Дмитрий
@ Дмитрию это не понравилось, так как в этом ответе -2. : D
dimpiax
Это плохой ответ, так как подстрочный оператор скрывает сложность O (n) функции индекса. Хороший API программирования использует только индекс для обозначения быстрого поиска.
Рагнариус
38

Короче в Swift 4/5:

var string = "123456"
string = String(string.prefix(3)) //"123"
string = String(string.suffix(3)) //"456"
Ильнур
источник
26

Преобразование вашего кода в Swift 4 также можно выполнить следующим образом:

let str = "Hello, playground"
let index = str.index(of: ",")!
let substr = str.prefix(upTo: index)

Вы можете использовать код ниже, чтобы получить новую строку:

let newString = String(str.prefix(upTo: index))
Тьерри Меццари
источник
17

подстрока (из: index) преобразована в [index ...]

Проверьте образец

let text = "1234567890"
let index = text.index(text.startIndex, offsetBy: 3)

text.substring(from: index) // "4567890"   [Swift 3]
String(text[index...])      // "4567890"   [Swift 4]
логово
источник
1
символы не поддерживаются в Swift 4, я думаю, вам нужно изменить пример, чтобы получить индекс для Swift 4
AbuTaareq
Это помогло мне. tnx
user1105951
17

Swift5

(Метод подстроки Java):

extension String {
    func subString(from: Int, to: Int) -> String {
       let startIndex = self.index(self.startIndex, offsetBy: from)
       let endIndex = self.index(self.startIndex, offsetBy: to)
       return String(self[startIndex...endIndex])
    }
}

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

var str = "Hello, Nick Michaels"
print(str.subString(from:7,to:20))
// print Nick Michaels
Август Лин
источник
2
Тем не менее работает в Swift 5. Я искал стиль подстроки Java ( fromк to-1, например , "Hello".substring(1,4)возвращается «флигель»). С небольшой модификацией ( startIndex..<endIndex) это лучшее решение, которое я нашел на данный момент, которое делает именно это с помощью всего лишь нескольких строк кода.
Неф
9

Некоторые полезные расширения:

extension String {
    func substring(from: Int, to: Int) -> String {
        let start = index(startIndex, offsetBy: from)
        let end = index(start, offsetBy: to - from)
        return String(self[start ..< end])
    }

    func substring(range: NSRange) -> String {
        return substring(from: range.lowerBound, to: range.upperBound)
    }
}
Johannes
источник
Интересно, я думал так же. Является ли String (строка ["http: //" .endIndex ...]) более понятным, чем устаревшая подстрока? line.substring (from: "http: //" .endIndex) возможно, пока они не получат заявленную цель удивительной обработки строк, им не следует отказываться от подстроки.
Посен
7

Пример uppercasedFirstCharacterудобства собственности в Swift3 и Swift4.

Свойство uppercasedFirstCharacterNewдемонстрирует, как использовать строковый индекс в Swift4.

extension String {

   public var uppercasedFirstCharacterOld: String {
      if characters.count > 0 {
         let splitIndex = index(after: startIndex)
         let firstCharacter = substring(to: splitIndex).uppercased()
         let sentence = substring(from: splitIndex)
         return firstCharacter + sentence
      } else {
         return self
      }
   }

   public var uppercasedFirstCharacterNew: String {
      if characters.count > 0 {
         let splitIndex = index(after: startIndex)
         let firstCharacter = self[..<splitIndex].uppercased()
         let sentence = self[splitIndex...]
         return firstCharacter + sentence
      } else {
         return self
      }
   }
}

let lorem = "lorem".uppercasedFirstCharacterOld
print(lorem) // Prints "Lorem"

let ipsum = "ipsum".uppercasedFirstCharacterNew
print(ipsum) // Prints "Ipsum"
Влад
источник
1
Если вы имеете в виду подстроку (с: range) -> self [range]
Арсен Вартбаронов
6

Вы можете создать свой собственный метод subString, используя расширение класса String, как показано ниже:

extension String {
    func subString(startIndex: Int, endIndex: Int) -> String {
        let end = (endIndex - self.count) + 1
        let indexStartOfText = self.index(self.startIndex, offsetBy: startIndex)
        let indexEndOfText = self.index(self.endIndex, offsetBy: end)
        let substring = self[indexStartOfText..<indexEndOfText]
        return String(substring)
    }
}
Chhaileng
источник
Если это будет принимать endIndex, он также должен уметь обрабатывать границы.
Джей
5

Создание SubString (префикс и суффикс) из String с помощью Swift 4:

let str : String = "ilike"
for i in 0...str.count {
    let index = str.index(str.startIndex, offsetBy: i) // String.Index
    let prefix = str[..<index] // String.SubSequence
    let suffix = str[index...] // String.SubSequence
    print("prefix \(prefix), suffix : \(suffix)")
}

Вывод

prefix , suffix : ilike
prefix i, suffix : like
prefix il, suffix : ike
prefix ili, suffix : ke
prefix ilik, suffix : e
prefix ilike, suffix : 

Если вы хотите сгенерировать подстроку между двумя индексами, используйте:

let substring1 = string[startIndex...endIndex] // including endIndex
let subString2 = string[startIndex..<endIndex] // excluding endIndex
Ашис лаха
источник
пусть префикс = str [... <index>] вместо str [.. <index>] отсутствует одна точка.
AbuTaareq
@AbuTaareq, о ком ты говоришь? пусть prefix = str [.. <index], это прекрасно. (префиксная строка). Попробуйте в игровой площадке, чтобы получить больше контекста.
Ашис Лаха
4

Я написал расширение строки для замены 'String: subString:'

extension String {
    
    func sliceByCharacter(from: Character, to: Character) -> String? {
        let fromIndex = self.index(self.index(of: from)!, offsetBy: 1)
        let toIndex = self.index(self.index(of: to)!, offsetBy: -1)
        return String(self[fromIndex...toIndex])
    }
    
    func sliceByString(from:String, to:String) -> String? {
        //From - startIndex
        var range = self.range(of: from)
        let subString = String(self[range!.upperBound...])
        
        //To - endIndex
        range = subString.range(of: to)
        return String(subString[..<range!.lowerBound])
    }
    
}

Использование : "Date(1511508780012+0530)".sliceByString(from: "(", to: "+")

Пример результата : "1511508780012"

PS: опционально нужно развернуть. Пожалуйста, добавьте проверку безопасности типа, где это необходимо.

byJeevan
источник
Осторожно: опционально необходимо развернуть. при необходимости добавьте проверку безопасности типа.
byJeevan
3

При программировании у меня часто бывают строки с простыми A-Za-z и 0-9. Нет необходимости в сложных действиях индекса. Это расширение основано на простых старых функциях left / mid / right.

extension String {

    // LEFT
    // Returns the specified number of chars from the left of the string
    // let str = "Hello"
    // print(str.left(3))         // Hel
    func left(_ to: Int) -> String {
        return "\(self[..<self.index(startIndex, offsetBy: to)])"
    }

    // RIGHT
    // Returns the specified number of chars from the right of the string
    // let str = "Hello"
    // print(str.left(3))         // llo
    func right(_ from: Int) -> String {
        return "\(self[self.index(startIndex, offsetBy: self.length-from)...])"
    }

    // MID
    // Returns the specified number of chars from the startpoint of the string
    // let str = "Hello"
    // print(str.left(2,amount: 2))         // ll
    func mid(_ from: Int, amount: Int) -> String {
        let x = "\(self[self.index(startIndex, offsetBy: from)...])"
        return x.left(amount)
    }
}
Винсент
источник
Отличная идея!! Грустно, однако, что есть необходимость абстрагировать Swift-функции только потому, что они постоянно меняют то, как все работает. Думаю, они хотят, чтобы мы все сосредоточились на конструкциях, а не на производительности. Во всяком случае, я сделал несколько небольших обновлений для вашего прекрасного кода: pastebin.com/ManWmNnW
Фредрик Йоханссон
2

с помощью этого метода вы можете получить конкретный диапазон строк. вам нужно передать начальный индекс и после этого общее количество символов, которое вы хотите.

extension String{
    func substring(fromIndex : Int,count : Int) -> String{
        let startIndex = self.index(self.startIndex, offsetBy: fromIndex)
        let endIndex = self.index(self.startIndex, offsetBy: fromIndex + count)
        let range = startIndex..<endIndex
        return String(self[range])
    }
}
джайеш канзария
источник
2

Это мое решение, без предупреждения, без ошибок, но идеально

let redStr: String = String(trimmStr[String.Index.init(encodedOffset: 0)..<String.Index.init(encodedOffset: 2)])
let greenStr: String = String(trimmStr[String.Index.init(encodedOffset: 3)..<String.Index.init(encodedOffset: 4)])
let blueStr: String = String(trimmStr[String.Index.init(encodedOffset: 5)..<String.Index.init(encodedOffset: 6)])
Виктор Джон
источник
Использование encodedOffsetявляется считается вредным и будет устаревшим .
Мартин Р
1

Надеюсь, это поможет немного больше: -

var string = "123456789"

Если вы хотите подстроку после определенного индекса.

var indexStart  =  string.index(after: string.startIndex )// you can use any index in place of startIndex
var strIndexStart   = String (string[indexStart...])//23456789

Если вы хотите подстроку после удаления какой-либо строки в конце.

var indexEnd  =  string.index(before: string.endIndex)
var strIndexEnd   = String (string[..<indexEnd])//12345678

Вы также можете создать индексы с помощью следующего кода: -

var  indexWithOffset =  string.index(string.startIndex, offsetBy: 4)
Анураг Бхакуни
источник
0

Надеюсь, это будет полезно.

extension String {
    func getSubString(_ char: Character) -> String {
        var subString = ""
        for eachChar in self {
            if eachChar == char {
                return subString
            } else {
                subString += String(eachChar)
            }
        }
        return subString
    }
}


let str: String = "Hello, playground"
print(str.getSubString(","))
Ананд Верма
источник
0
var str = "Hello, playground"
let indexcut = str.firstIndex(of: ",")
print(String(str[..<indexcut!]))
print(String(str[indexcut!...]))

Вы можете попробовать таким образом и получите надлежащие результаты.

user1828845
источник