Quando eu uso o loop for no Playground, tudo funcionou bem, até que eu mudei o primeiro parâmetro do loop for para o valor mais alto. (iterado em ordem decrescente)
Isso é um inseto? Alguém mais o teve?
for index in 510..509
{
var a = 10
}
O contador que exibe o número de iterações que serão executadas continua correndo ...
ios
swift
swift-playground
Krishnan
fonte
fonte
Respostas:
O Xcode 6 beta 4 adicionou duas funções para iterar em intervalos com uma etapa diferente de um:,
stride(from: to: by:)
que é usado com intervalos exclusivos estride(from: through: by:)
, que é usado com intervalos inclusivos.Para iterar em um intervalo na ordem inversa, eles podem ser usados como abaixo:
Observe que nenhum desses é uma
Range
função de membro. São funções globais que retornam umaStrideTo
ou umaStrideThrough
estrutura, definidas de forma diferente daRange
estrutura.Uma versão anterior desta resposta usava a
by()
função membro daRange
estrutura, que foi removida na versão beta 4. Se você quiser ver como isso funcionou, verifique o histórico de edição.fonte
5.stride(to: 1, by: -1)
ou5.stride(through: 1, by: -1)
:
operador iterando implicitamente para baixo, fazendo com que seus loops sejam executados quando eles pensam que os ignorariam. É muito conveniente para uso interativo, mas é extremamente propenso a erros em scripts, a ponto de os guias de estilo não recomendarem o uso .Aplique a função reversa ao intervalo para iterar para trás:
Para o Swift 1.2 e versões anteriores:
Também funciona com intervalos semi-abertos:
Nota:
reverse(1...10)
cria uma matriz do tipo[Int]
, portanto, embora isso possa ser bom para pequenos intervalos, seria aconselhável usarlazy
como mostrado abaixo ou considerar astride
resposta aceita se o seu intervalo for grande.Para evitar criar uma grande matriz, use
lazy
junto comreverse()
. O teste a seguir é executado com eficiência em um Playground, mostrando que ele não está criando uma matriz com um trilhão deInt
s!Teste:
Para o Swift 2.0 no Xcode 7:
Observe que no Swift 2.0,
(1...1_000_000_000_000).reverse()
é do tipoReverseRandomAccessCollection<(Range<Int>)>
, então isso funciona bem:O Swift 3.0
reverse()
foi renomeado parareversed()
:fonte
reversed
pode copiar a coleção, no entanto. Pelo menos, é assim que entendo a documentaçãoData
.Atualizado para o Swift 3
A resposta abaixo é um resumo das opções disponíveis. Escolha o que melhor se adapta às suas necessidades.
reversed
: números em um intervalofrente
Para trás
reversed
: elementos emSequenceType
frente
Para trás
reversed
: elementos com um índiceÀs vezes, é necessário um índice ao percorrer uma coleção. Para isso você pode usar
enumerate()
, o que retorna uma tupla. O primeiro elemento da tupla é o índice e o segundo elemento é o objeto.frente
Para trás
Observe que, como Ben Lachman observou em sua resposta , você provavelmente deseja fazer
.enumerated().reversed()
mais do que.reversed().enumerated()
(o que aumentaria o número de índices).stride: numbers
Stride é uma maneira de iterar sem usar um intervalo. Existem duas formas. Os comentários no final do código mostram qual seria a versão do intervalo (assumindo que o tamanho do incremento seja 1).
frente
Para trás
Alterar o tamanho do incremento para
-1
permite retroceder.Observe a diferença
to
ethrough
.stride: elementos de SequenceType
Avançar em incrementos de 2
Estou usando
2
neste exemplo apenas para mostrar outra possibilidade.Para trás
Notas
O @matt tem uma solução interessante onde ele define seu próprio operador reverso e o chama
>>>
. Não é preciso muito código para definir e é usado assim:Confira o C-Style For Loops Removido do Swift 3
fonte
Swift 4 em diante
fonte
Com o Swift 5, de acordo com suas necessidades, você pode escolher um dos quatro exemplos de código do Playground a seguir para resolver seu problema.
# 1 Usando o
ClosedRange
reversed()
métodoClosedRange
tem um método chamadoreversed()
.reversed()
O método tem a seguinte declaração:Uso:
Como alternativa, você pode usar o
Range
reversed()
método:# 2 Usando a
sequence(first:next:)
funçãoA Biblioteca Padrão Swift fornece uma função chamada
sequence(first:next:)
.sequence(first:next:)
tem a seguinte declaração:Uso:
# 3 Usando a
stride(from:through:by:)
funçãoA Biblioteca Padrão Swift fornece uma função chamada
stride(from:through:by:)
.stride(from:through:by:)
tem a seguinte declaração:Uso:
Como alternativa, você pode usar
stride(from:to:by:)
:# 4 Usando
AnyIterator
init(_:)
inicializadorAnyIterator
tem um inicializador chamadoinit(_:)
.init(_:)
tem a seguinte declaração:Uso:
Se necessário, você pode refatorar o código anterior criando um método de extensão
Int
e envolvendo seu iterador nele:fonte
Para Swift 2.0 e superior, você deve aplicar reverso em uma coleção de intervalos
Foi renomeado para .reversed () no Swift 3.0
fonte
No Swift 4 e no último
fonte
Swift 4.0
Se você deseja incluir o
to
valor:fonte
Se alguém quiser iterar através de uma matriz (
Array
ou mais geralmente algumaSequenceType
) ao contrário. Você tem algumas opções adicionais.Primeiro você pode
reverse()
a matriz e percorrê-la normalmente. No entanto, prefiro usar aenumerate()
maior parte do tempo, pois gera uma tupla contendo o objeto e seu índice.A única coisa a observar aqui é que é importante chamá-los na ordem correta:
for (index, element) in array.enumerate().reverse()
gera índices em ordem decrescente (que é o que geralmente espero). enquanto que:
for (index, element) in array.reverse().enumerate()
(que é mais parecido com o do NSArrayreverseEnumerator
)retrocede a matriz, mas gera índices ascendentes.
fonte
quanto ao Swift 2.2, Xcode 7.3 (10 de junho de 2016):
Resultado :
fonte
Você pode usar o
while
loop C-Style . Isso funciona muito bem no Swift 3:fonte
Você pode usar o método reversed () para reverter valores facilmente.
O método reversed () reverte os valores.
fonte
fonte