Обратный ассортимент в Swift


есть ли способ работать с обратными диапазонами в Swift?

например:

for i in 5...1 {
  // do something
}

бесконечный цикл.

Я знаю, что могу использовать 1..5 вместо расчета j = 6 - i и использовать j как мой индекс. Мне просто интересно, есть ли что-нибудь более разборчивое?

7 80

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 1

Stride был переработан в 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
}

Xcode 7, beta 2:

for i in (1...5).reverse() {
  // do something
}

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> ссылка

Это может быть другой способ сделать это.

(1...5).reversed().forEach { print() }

функция Reverse () используется для обратного номера.

Var n:Int / / введите число

для i в 1...Номер.обратный() { Print (i) }