Faixa reversa em Swift

Existe uma maneira de trabalhar com intervalos reversos no Swift?

Por exemplo:

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

é um loop infinito.

Eu sei que eu posso usar 1..5 vez disso, calcular j = 6 - i e usar j como meu índice. Eu só estava me perguntando se havia algo mais legível?

Atualização Para o mais recente Swift 3 (ainda funciona no Swift 4)

Você pode usar o método reversed() em um intervalo

 for i in (1...5).reversed() { print(i) } // 5 4 3 2 1 

Ou stride(from:through:by:) method

 for i in stride(from:5,through:1,by:-1) { print(i) } // 5 4 3 2 1 

stide(from:to:by:) é semelhante mas exclui o último valor

 for i in stride(from:5,to:0,by:-1) { print(i) } // 5 4 3 2 1 

Atualização para mais recente Swift 2

Em primeiro lugar, as extensões de protocolo alteram a forma como o reverse é usado:

for i in (1...5).reverse() { print(i) } // 5 4 3 2 1

Stride foi reformulado no Xcode 7 Beta 6. O novo uso é:

 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 

Também funciona para Doubles :

 for i in 0.5.stride(to:-0.1, by: -0.1) { print(i) } 

Desconfie de ponto flutuante compara aqui para os limites.

Edição anterior do Swift 1.2 : A partir do Xcode 6 Beta 4, por e ReverseRange não existem mais: [

Se você está apenas olhando para inverter um intervalo, a function inversa é tudo que você precisa:

 for i in reverse(1...5) { println(i) } // prints 5,4,3,2,1 

Conforme postado por 0x7fffffff, há uma nova construção de passo que pode ser usada para iterar e incrementar por inteiros arbitrários. A Apple também afirmou que o suporte de ponto flutuante está chegando.

Originado de sua resposta:

 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 } 

Há algo de perturbador na assimetria disso:

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

... em oposição a isso:

 for i in 1..<5 { 

Isso significa que toda vez que eu quero fazer um intervalo reverso, eu tenho que lembrar de colocar os parênteses, mais eu tenho que escrever isso .reverse() no final, saindo como um polegar dolorido. Isso é realmente feio em comparação com os loops de estilo C, que são simétricos contando e decrescendo. Então, eu costumava usar loops de estilo C em vez disso. Mas no Swift 2.2, os loops de estilo C estão indo embora! Então eu tive que correr atrás de replace todos os meus loops decrementantes de estilo C por essa construção feia de .reverse() imaginando o tempo todo, por que não existe um operador de faixa reversa?

Mas espere! Isso é Swift - podemos definir nossos próprios operadores !! Aqui vamos nós:

 infix operator >>> { associativity none precedence 135 } func >>> (end:Pos, start:Pos) -> ReverseRandomAccessCollection<(Range)> { return (start.. 

Então agora eu posso dizer:

 for i in 5>>>1 {print(i)} // 4, 3, 2, 1 

Isso cobre apenas o caso mais comum que ocorre no meu código, mas é de longe o caso mais comum, então é tudo o que preciso no momento.

Eu tive uma espécie de crise interna chegando com o operador. Eu teria gostado de usar >.. , como sendo o contrário de ..< , mas isso não é legal: você não pode usar um ponto depois de um não-ponto, ele aparece. Eu considerei ..> mas decidi que era muito difícil distinguir de. A coisa boa sobre >>> é que grita com você: "para baixo !" (Claro que você está livre para criar outro operador. Mas meu conselho é: para super simetria, defina <<< para fazer o que ..< faz, e agora você tem <<< e >>> que são simétrico e fácil de digitar.)


Versão Swift 3 (Xcode 8 seed 6):

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

Versão Swift 4 (Xcode 9 beta 3):

 infix operator >>> : RangeFormationPrecedence func >>>(maximum: Bound, minimum: Bound) -> ReversedRandomAccessCollection> where Bound : Comparable & Strideable { return (minimum.. 

Versão 4.2 do Swift (Xcode 10 beta 1):

 infix operator >>> : RangeFormationPrecedence func >>>(maximum: Bound, minimum: Bound) -> ReversedRandomAccessCollection> where Bound : Strideable { return (minimum.. 

Parece que as respostas a esta pergunta mudaram um pouco à medida que progredimos através dos betas. A partir do beta 4, tanto a function by() quanto o tipo ReversedRange foram removidos do idioma. Se você estiver procurando fazer um intervalo invertido, suas opções agora são as seguintes:

1: Crie um intervalo de avanço e, em seguida, use a function reverse() para invertê-lo.

 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: Use as novas funções stride() que foram adicionadas na versão beta 4, que inclui funções para especificar os índices inicial e final, bem como o valor para iterar por.

 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 } 

Observe que também incluí o novo operador de faixa exclusiva neste post também. .. foi substituído por ..< .

Edit: A partir das notas de lançamento do Xcode 6 beta 5 , a Apple adicionou a seguinte sugestão para lidar com isso:

ReverseRange foi removido; use preguiçoso (x ..

Aqui está um exemplo.

 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+ : você pode fazer assim:

 for i in sequence(first: 10, next: {$0 - 1}) { guard i >= 0 else { break } print(i) } 

Resultado : 10, 9, 8 … 0

Você pode personalizá-lo como quiser. Para mais informações, leia a referência func sequence

Esta poderia ser outra maneira de fazer isso.

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

A function reversa () é usada para o número reverso.

Var n: Int // Digite o número

Para i em 1 … Num.reverse () {Print (i)}