Обратный ассортимент в Swift
есть ли способ работать с обратными диапазонами в Swift?
например:
for i in 5...1 {
// do something
}
бесконечный цикл.
Я знаю, что могу использовать 1..5 вместо расчета j = 6 - i и использовать j как мой индекс. Мне просто интересно, есть ли что-нибудь более разборчивое?
7 ответов:
обновление для последнего Swift 3 (все еще работает в Swift 4)
можно использовать
reversed()метод на диапазонеfor i in (1...5).reversed() { print(i) } // 5 4 3 2 1или
stride(from:through:by:)методfor i in stride(from:5,through:1,by:-1) { print(i) } // 5 4 3 2 1
stide(from:to:by:)аналогично, но исключает последнее значениеfor i in stride(from:5,to:0,by:-1) { print(i) } // 5 4 3 2 1обновление для последнего Swift 2
прежде всего, расширения протокола меняются как
reverseиспользуется:
for i in (1...5).reverse() { print(i) } // 5 4 3 2 1Stride был переработан в Xcode 7 Beta 6. Новое использование:
for i in 0.stride(to: -8, by: -2) { print(i) } // 0 -2 -4 -6 for i in 0.stride(through: -8, by: -2) { print(i) } // 0 -2 -4 -6 -8он также работает для
Doubles:for i in 0.5.stride(to:-0.1, by: -0.1) { print(i) }будьте осторожны с плавающей точкой сравнивает здесь для границ.
ранее редактировать для Swift 1.2: начиная с Xcode 6 Beta 4, by и ReverseRange больше не существует :[
если вы просто хотите изменить диапазон,реверс
есть что-то тревожное в асимметрии этого:
for i in (1..<5).reverse()...в противоположность этому:
for i in 1..<5 {это означает, что каждый раз, когда я хочу сделать обратный диапазон, я должен помнить, чтобы поставить скобки, плюс я должен написать, что
.reverse()на конце, торчит, как больной палец. Это действительно уродливо по сравнению с C-стилем для петель, которые симметричны, считая вверх и отсчитывая вниз. Поэтому я, как правило, использовал C-стиль для циклов вместо этого. Но в Swift 2.2, C-стиль для петель уходит! Так что мне приходилось бегать вокруг, заменяя все мое уменьшение с-стиль петли с этой уродливой.reverse()построить-интересно все время, почему на земле нет оператора обратного диапазона?но подождите! Это Swift - нам разрешено определять наших собственных операторов!! Здесь мы идем:
infix operator >>> { associativity none precedence 135 } func >>> <Pos : ForwardIndexType where Pos : Comparable>(end:Pos, start:Pos) -> ReverseRandomAccessCollection<(Range<Pos>)> { return (start..<end).reverse() }так что теперь я могу сказать:
for i in 5>>>1 {print(i)} // 4, 3, 2, 1это охватывает только самый распространенный случай, который происходит в моем коде, но это и самый распространенный случай, так что это все, что мне нужно на данный момент.
у меня был какой-то внутренний кризис, связанный с оператором. Я бы хотел использовать
>.., как реверс..<, но это не законно: вы не можете использовать точку после номера-точка, кажется. Я считал..>но решил, что это слишком трудно отличить от..<. Хорошая вещь о>>>это он кричит на тебя:"вниз к!"( Конечно, вы можете придумать другой оператор. Но мой совет: для супер симметрии определите<<<что делать..<делает, и теперь у вас есть<<<и>>>которые симметричны и просты в вводе.)
Swift 3 version (Xcode 8 seed 6):
infix operator >>> : RangeFormationPrecedence func >>><Bound>(maximum: Bound, minimum: Bound) -> ReversedRandomAccessCollection<CountableRange<Bound>> where Bound : Comparable, Bound.Stride : Integer { return (minimum..<maximum).reversed() }версия Swift 4 (Xcode 9 beta 3):
infix operator >>> : RangeFormationPrecedence func >>><Bound>(maximum: Bound, minimum: Bound) -> ReversedRandomAccessCollection<CountableRange<Bound>> where Bound : Comparable & Strideable { return (minimum..<maximum).reversed() }версия Swift 4.2 (Xcode 10 beta 1):
infix operator >>> : RangeFormationPrecedence func >>><Bound>(maximum: Bound, minimum: Bound) -> ReversedRandomAccessCollection<Range<Bound>> where Bound : Strideable { return (minimum..<maximum).reversed() }
похоже, что ответы на этот вопрос немного изменились по мере того, как мы продвигались через бета. По состоянию на бета 4, оба и
ReversedRangeтип был удален из языка. Если вы хотите сделать обратный диапазон, ваши варианты теперь следующие:1: Создайте прямой диапазон, а затем используйте
reverse()функция для того чтобы обратить его.for x in reverse(0 ... 4) { println(x) // 4, 3, 2, 1, 0 } for x in reverse(0 ..< 4) { println(x) // 3, 2, 1, 0 }2: Используйте новый
stride()функции которые были добавлены в бета-версии 4, который включает в себя функции чтобы указать начальный и конечный индексы, а также количество итераций.for x in stride(from: 0, through: -8, by: -2) { println(x) // 0, -2, -4, -6, -8 } for x in stride(from: 6, to: -2, by: -4) { println(x) // 6, 2 }обратите внимание, что я также включил новый оператор эксклюзивного диапазона в этот пост.
..был заменен..<.Edit: из Xcode 6 бета 5 примечания к выпуску, Apple добавила следующее предложение для обработки этого:
ReverseRange был удален; используйте lazy(x..
вот образец.
for i in lazy(0...5).reverse() { // 0, 1, 2, 3, 4, 5 }
Swift 3, 4+: вы можете сделать это так:
for i in sequence(first: 10, next: { - 1}) { guard i >= 0 else { break } print(i) }результат: 10, 9, 8 ... 0
Вы можете настроить его так, как вам нравится. Для получения дополнительной информации читайте
func sequence<T>ссылка