Existe uma maneira de trabalhar com intervalos reversos em Swift?
Por exemplo:
for i in 5...1 {
// do something
}
é um loop infinito.
Em versões mais recentes do Swift, esse código é compilado, mas em tempo de execução dá o erro:
Erro fatal: não é possível formar Range com upperBound <lowerBound
Eu sei que posso usar em 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.
Respostas:
Atualizar para o Swift 3 mais recente (ainda funciona no Swift 4)
Você pode usar o
reversed()
método em um intervaloOu
stride(from:through:by:)
métodostide(from:to:by:)
é semelhante, mas exclui o último valorAtualização para o último Swift 2
Em primeiro lugar, as extensões de protocolo mudam a forma como
reverse
é usado:for i in (1...5).reverse() { print(i) } // 5 4 3 2 1
Stride foi retrabalhado no Xcode 7 Beta 6. O novo uso é:
Também funciona para
Doubles
:Tenha cuidado com as comparações de ponto flutuante aqui para os limites.
Edição anterior para Swift 1.2 : a partir do Xcode 6 Beta 4, por e ReverseRange não existem mais: [
Se você está apenas procurando inverter um intervalo, a função reversa é tudo que você precisa:
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.
Proveniente de sua resposta:
fonte
(1...5).reverse()
(como uma chamada de função), atualize sua resposta. (Como são apenas dois caracteres, não consegui editar sua postagem.)(1...5).reversed()
. Além disso, o exemplo para.stride()
não funciona e, emstride(from:to:by:)
vez disso , precisa da função free .stride
código do swift 3 está ligeiramente incorreto. para incluir o número 1, você precisaria usarthrough
oposto ato
este:for i in stride(from:5,through:1,by:-1) { print(i) }
reversed
possui uma complexidade de O (1) porque apenas envolve a coleção original e não requer uma iteração para construí-la.Há algo preocupante sobre a assimetria disso:
... em oposição a este:
Isso significa que toda vez que eu quiser fazer um intervalo reverso, tenho que me lembrar de colocar os parênteses, além disso, tenho que escrever isso
.reverse()
no final, saindo como um polegar machucado. Isso é realmente feio em comparação com os loops for do estilo C, que são simétricos em contagem crescente e decrescente. Portanto, eu tendia a usar loops for no estilo C. Mas no Swift 2.2, os loops for estilo C estão desaparecendo! Então tive que me apressar para substituir todos os meus loops for de estilo C decrescentes por esta.reverse()
construção feia - me perguntando o tempo todo, por que diabos não existe um operador de reversão?Mas espere! Este é o Swift - temos permissão para definir nossos próprios operadores !! Aqui vamos nós:
Agora posso dizer:
Isso cobre apenas o caso mais comum que ocorre em meu código, mas é de longe o caso mais comum, então é tudo de que preciso no momento.
Tive uma espécie de crise interna chegando com a operadora. Eu gostaria de usar
>..
, como sendo o reverso de..<
, mas isso não é legal: você não pode usar um ponto após um não-ponto, parece. Eu considerei,..>
mas decidi que era muito difícil distinguir..<
. O bom>>>
disso é que grita com você: " até !" (Claro que você está livre para sugerir outro operador. Mas meu conselho é: para supersimetria, defina o<<<
que..<
faz e agora você tem<<<
e>>>
quais são simétricos e fáceis de digitar.)Versão Swift 3 (Xcode 8 seed 6):
Versão Swift 4 (Xcode 9 beta 3):
Versão 4.2 do Swift (Xcode 10 beta 1):
Versão do Swift 5 (Xcode 10.2.1):
fonte
>>>
operadora é muito legal! Espero que os designers do Swift prestem atenção a coisas como essa, porque colarreverse()
no final das expressões entre parênteses parece estranho. Não há razão para que eles não possam lidar com os5>..0
intervalos automaticamente, porque oForwardIndexType
protocolo fornece umdistanceTo()
operador perfeitamente razoável que pode ser usado para descobrir se o passo deve ser positivo ou negativo.Parece que as respostas a essa pergunta mudaram um pouco à medida que avançamos nos betas. No beta 4, tanto a
by()
função quanto oReversedRange
tipo foram removidos do idioma. Se você deseja fazer um intervalo invertido, suas opções agora são as seguintes:1: Crie um intervalo de avanço e, em seguida, use a
reverse()
função para invertê-lo.2: Use as novas
stride()
funções que foram adicionadas no beta 4, que inclui funções para especificar os índices inicial e final, bem como a quantidade de iteração.Observe que também incluí o novo operador de alcance exclusivo neste artigo.
..
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:
Aqui está um exemplo.
fonte
lazy(0....5).reverse()
e não vejo as notas de lançamento do beta 5. Você conhece outras discussões sobre este assunto? Além disso, FYI, os números dentro dessefor
loop estão ao contrário em seu exemplo.// 0, 1, 2, 3, 4, 5
mas na verdade deveria ser revertido. O comentário é enganoso.Xcode 7, beta 2:
fonte
Swift 3, 4+ : você pode fazer assim:
resultado : 10, 9, 8 ... 0
Você pode personalizá-lo da maneira que quiser. Para mais informações, leia a
func sequence<T>
referênciafonte
Esta poderia ser outra maneira de fazer isso.
fonte
A função Reverse () é usada para o número reverso.
Var n: Int // Insira o número
Para i em 1 ... n.reverse () {Imprimir (i)}
fonte