Обратный диапазон в Swift

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

Например:

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

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

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

87 голосов | спросил Eduardo 23 J0000006Europe/Moscow 2014, 22:10:31

7 ответов


0

Обновление для последней версии 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 reverse(1...5) { println(i) } // prints 5,4,3,2,1

Как опубликовано 0x7fffffff , существует новая конструкция stride , которую можно использовать для итерации и приращения произвольными целыми числами. Apple также заявила, что ожидается поддержка с плавающей запятой.

Источник из его ответа:

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
}
ответил Jack 23 J0000006Europe/Moscow 2014, 22:14:52
0

Есть что-то тревожное в асимметрии этого:

for i in (1..<5).reverse()

... в отличие от этого:

for i in 1..<5 {

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

Это только самый распространенный случай, который встречается в моем коде, но он является самым распространенным, так что это все, что мне нужно в данный момент.

У меня был своего рода внутренний кризис с оператором. Я хотел бы использовать >.., как обратное к ..<, но это недопустимо: вы не можете использовать точку после точки без точки, это кажется. Я рассмотрел ..>, но решил, что его слишком сложно отличить от ..<. Хорошая вещь в >>> заключается в том, что он кричит вам: « вниз в!» (Конечно, вы можете придумать другой оператор. Но мой совет: для суперсимметрии определите <<<, чтобы сделать то, что ---- +: = 12 =: + ----, и теперь у вас есть ..< и <<<, которые являются симметричными и простыми для ввода.)


Версия Swift 3 (Xcode 8 seed 6):

>>>

Версия Swift 4 (Xcode 9 beta 3):

infix operator >>> : RangeFormationPrecedence
func >>><Bound>(maximum: Bound, minimum: Bound) ->
    ReversedRandomAccessCollection<CountableRange<Bound>> 
    where Bound : Comparable, Bound.Stride : Integer {
        return (minimum..<maximum).reversed()
}

Версия Swift 4.2 (Xcode 10 beta 1):

infix operator >>> : RangeFormationPrecedence
func >>><Bound>(maximum: Bound, minimum: Bound)
    -> ReversedRandomAccessCollection<CountableRange<Bound>>
    where Bound : Comparable & Strideable { 
        return (minimum..<maximum).reversed()
}
ответил matt 28 FebruaryEurope/MoscowbSun, 28 Feb 2016 18:57:27 +0300000000pmSun, 28 Feb 2016 18:57:27 +030016 2016, 18:57:27
0

Похоже, что ответы на этот вопрос немного изменились по мере прохождения бета-версий. Начиная с бета-версии 4 и функция by(), и функция 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
}

Обратите внимание, что в этот пост я также включил нового оператора исключительного диапазона. .. было заменено на ..<.

Изменить . Из примечаний к выпуску бета-версии Xcode 6 , Apple добавила следующее предложение для обработки этого:

  

ReverseRange был удален; использовать ленивый (х ..

Вот пример.

for i in lazy(0...5).reverse() {
    // 0, 1, 2, 3, 4, 5
}
ответил Mick MacCallum 24 J000000Thursday14 2014, 00:56:50
0

Xcode 7, бета 2:

for i in (1...5).reverse() {
  // do something
}
ответил leanne 6 J000000Monday15 2015, 00:50:06
0

Swift 3, 4 + : вы можете сделать это следующим образом:

for i in sequence(first: 10, next: {$0 - 1}) {

    guard i >= 0 else {
        break
    }
    print(i)
}

результат : 10, 9, 8 ... 0

Вы можете настроить его так, как вам нравится. Для получения дополнительной информации читайте func sequence<T> ссылка

ответил nCod3d 4 J000000Monday16 2016, 19:10:35
0

Это может быть еще один способ сделать это.

(1...5).reversed().forEach { print($0) }
ответил David H 20 WedEurope/Moscow2017-12-20T16:39:45+03:00Europe/Moscow12bEurope/MoscowWed, 20 Dec 2017 16:39:45 +0300 2017, 16:39:45
0

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

Var n: Int //Введите номер

Для i в 1 ... n.reverse () {         Печать (я) }

ответил laxrajpurohit 12 PM00000020000001431 2018, 14:39:14

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132