Как создать диапазон в Swift?
в Objective-c мы создаем диапазон с помощью NSRange
NSRange range;
Итак, как создать диапазон в Swift?
9 ответов:
обновлено для Swift 4
Swift диапазоны являются более сложными, чем
NSRange
, и они не стали легче в Swift 3. Если вы хотите попытаться понять причины некоторых из этих сложностей, прочитайте этой и этой. Я просто покажу вам, как их создавать и когда вы можете их использовать.Закрытые Диапазоны:
a...b
этой оператор диапазона создает быстрый диапазон, который включает в себя оба элемента
a
и элементb
, даже еслиb
- это максимально возможное значение для типа (например,Int.max
). Существует два различных типа закрытых диапазонов:ClosedRange
иCountableClosedRange
.1.
ClosedRange
элементы всех диапазонов в Swift сопоставимы (т. е. они соответствуют сопоставимых протокола). Это позволяет получить доступ к элементам в диапазоне из коллекции. Вот пример:
let myRange: ClosedRange = 1...3 let myArray = ["a", "b", "c", "d", "e"] myArray[myRange] // ["b", "c", "d"]
однако, a
ClosedRange
не является счетным (т. е. не соответствует протоколу последовательности). Это означает, что вы не можете перебирать элементы с помощьюfor
петли. Для этого вам нужноCountableClosedRange
.2.
CountableClosedRange
это похоже на последний, за исключением того, что теперь диапазон также может быть повторен.
let myRange: CountableClosedRange = 1...3 let myArray = ["a", "b", "c", "d", "e"] myArray[myRange] // ["b", "c", "d"] for index in myRange { print(myArray[index]) }
Полуоткрытые Диапазоны:
a..<b
этот оператор диапазона включает в себя элемент
a
но не элементb
. Как и выше, существует два различных типа полуоткрытых диапазонов:Range
иCountableRange
.1.
Range
С
ClosedRange
, вы можете получить доступ к элементам коллекции сRange
. Пример:let myRange: Range = 1..<3 let myArray = ["a", "b", "c", "d", "e"] myArray[myRange] // ["b", "c"]
опять же, вы не можете перебирать
Range
потому что это только сопоставимо, а не шагает.2.
CountableRange
A
CountableRange
позволяет итерации.let myRange: CountableRange = 1..<3 let myArray = ["a", "b", "c", "d", "e"] myArray[myRange] // ["b", "c"] for index in myRange { print(myArray[index]) }
NSRange
вы можете (должны) по-прежнему использовать
NSRange
время от времени в Swift (при создании отнести строки, например), поэтому полезно знать, как сделать один.let myNSRange = NSRange(location: 3, length: 2)
обратите внимание, что это расположение и длина, а не начальный индекс и конечный индекс. Пример здесь похож по смыслу на Swift range
3..<5
. Однако, поскольку типы различны, они не являются взаимозаменяемыми.диапазоны со строки
The
...
и
Xcode 8 beta 2 * Swift 3
let myString = "Hello World" let myRange = myString.startIndex..<myString.index(myString.startIndex, offsetBy: 5) let mySubString = myString.substring(with: myRange) // Hello
Xcode 7 * Swift 2.0
let myString = "Hello World" let myRange = Range<String.Index>(start: myString.startIndex, end: myString.startIndex.advancedBy(5)) let mySubString = myString.substringWithRange(myRange) // Hello
или просто
let myString = "Hello World" let myRange = myString.startIndex..<myString.startIndex.advancedBy(5) let mySubString = myString.substringWithRange(myRange) // Hello
использовать такой
var start = str.startIndex // Start at the string's start index var end = advance(str.startIndex, 5) // Take start index and advance 5 characters forward var range: Range<String.Index> = Range<String.Index>(start: start,end: end) let firstFiveDigit = str.substringWithRange(range) print(firstFiveDigit)
выход : Привет
Я нахожу удивительным, что даже в Swift 4 до сих пор нет простого собственного способа выразить диапазон строк с помощью Int. Единственные строковые методы, которые позволяют вам предоставить Int как способ получения подстроки по диапазону, - это
prefix
иsuffix
.полезно иметь под рукой некоторые утилиты преобразования, так что мы можем говорить, как NSRange при разговоре со строкой. Вот утилита, которая принимает местоположение и длину, как и NSRange, и возвращает a
Range<String.Index>
:func range(_ start:Int, _ length:Int) -> Range<String.Index> { let i = self.index(start >= 0 ? self.startIndex : self.endIndex, offsetBy: start) let j = self.index(i, offsetBy: length) return i..<j }
например,
"hello".range(0,1)"
- этоRange<String.Index>
обнимая первый символ"hello"
. В качестве бонуса, я разрешил отрицательные места:"hello".range(-1,1)"
- этоRange<String.Index>
обнимая последний символ"hello"
.полезно также преобразовать
Range<String.Index>
к NSRange, для тех моментов, когда вам нужно поговорить с Cocoa (например, при работе с диапазонами атрибутов NSAttributedString). Swift 4 предоставляет собственный способ сделать это:let nsrange = NSRange(range, in:s) // where s is the string
мы таким образом, можно написать еще одну утилиту, где мы переходим непосредственно из строкового местоположения и длины в NSRange:
extension String { func nsRange(_ start:Int, _ length:Int) -> NSRange { return NSRange(self.range(start,length), in:self) } }
Если кто-то хочет создать объект NSRange можно создать как:
let range: NSRange = NSRange.init(location: 0, length: 5)
это создаст диапазон с позицией 0 и длиной 5
Я создал следующее расширение:
extension String { func substring(from from:Int, to:Int) -> String? { if from<to && from>=0 && to<self.characters.count { let rng = self.startIndex.advancedBy(from)..<self.startIndex.advancedBy(to) return self.substringWithRange(rng) } else { return nil } } }
пример использования:
print("abcde".substring(from: 1, to: 10)) //nil print("abcde".substring(from: 2, to: 4)) //Optional("cd") print("abcde".substring(from: 1, to: 0)) //nil print("abcde".substring(from: 1, to: 1)) //nil print("abcde".substring(from: -1, to: 1)) //nil
func replace(input: String, start: Int,lenght: Int, newChar: Character) -> String { var chars = Array(input.characters) for i in start...lenght { guard i < input.characters.count else{ break } chars[i] = newChar } return String(chars)
}
Вы можете использовать такой
let nsRange = NSRange(location: someInt, length: someInt)
а в
let myNSString = bigTOTPCode as NSString //12345678 let firstDigit = myNSString.substringWithRange(NSRange(location: 0, length: 1)) //1 let secondDigit = myNSString.substringWithRange(NSRange(location: 1, length: 1)) //2 let thirdDigit = myNSString.substringWithRange(NSRange(location: 2, length: 4)) //3456