Cuando uso el bucle for en Playground, todo funcionó bien, hasta que cambié el primer parámetro de for loop por el valor más alto. (iterado en orden descendente)
¿Es esto un error? ¿Alguien más lo tiene?
for index in 510..509
{
var a = 10
}
El contador que muestra el número de iteraciones que se ejecutarán sigue marcando ...
ios
swift
swift-playground
Krishnan
fuente
fuente
Respuestas:
Xcode 6 beta 4 agregó dos funciones para iterar en rangos con un paso distinto de uno:
stride(from: to: by:)
que se usa con rangos exclusivos ystride(from: through: by:)
que se usa con rangos inclusivos.Para iterar en un rango en orden inverso, se pueden usar de la siguiente manera:
Tenga en cuenta que ninguno de esos es una
Range
función miembro. Son funciones globales que devuelvenStrideTo
unaStrideThrough
estructura o una estructura, que se definen de manera diferente a laRange
estructura.Una versión anterior de esta respuesta utilizaba la
by()
función miembro de laRange
estructura, que se eliminó en la versión beta 4. Si desea ver cómo funcionó, consulte el historial de edición.fuente
5.stride(to: 1, by: -1)
o5.stride(through: 1, by: -1)
:
operador implícitamente iterando hacia abajo, haciendo que sus bucles se ejecuten cuando pensaron que los omitiría. Es muy conveniente para el uso interactivo, pero terriblemente propenso a errores en los scripts, hasta el punto en que las guías de estilo recomiendan no usarlo .Aplique la función inversa al rango para iterar hacia atrás:
Para Swift 1.2 y versiones anteriores:
También funciona con rangos medio abiertos:
Nota:
reverse(1...10)
crea una matriz de tipos[Int]
, por lo que si bien esto podría estar bien para rangos pequeños, sería aconsejable usarlazy
como se muestra a continuación o considerar lastride
respuesta aceptada si su rango es grande.Para evitar crear una gran matriz, use
lazy
junto conreverse()
. ¡La siguiente prueba se ejecuta eficientemente en un área de juegos que muestra que no está creando una matriz con un billón deInt
s!Prueba:
Para Swift 2.0 en Xcode 7:
Tenga en cuenta que en Swift 2.0,
(1...1_000_000_000_000).reverse()
es de tipoReverseRandomAccessCollection<(Range<Int>)>
, por lo que funciona bien:Para Swift 3.0 se
reverse()
ha cambiado el nombre areversed()
:fuente
reversed
aunque puede copiar la colección. Al menos, así es como entiendo la documentaciónData
.Actualizado para Swift 3
La respuesta a continuación es un resumen de las opciones disponibles. Elija el que mejor se adapte a sus necesidades.
reversed
: números en un rangoAdelante
Hacia atrás
reversed
: elementos enSequenceType
Adelante
Hacia atrás
reversed
: elementos con un índiceA veces se necesita un índice cuando se itera por una colección. Para eso puedes usar
enumerate()
, que devuelve una tupla. El primer elemento de la tupla es el índice y el segundo elemento es el objeto.Adelante
Hacia atrás
Tenga en cuenta que, como señaló Ben Lachman en su respuesta , es probable que desee hacerlo en
.enumerated().reversed()
lugar de.reversed().enumerated()
(lo que aumentaría los números de índice).zancada: números
Stride es una forma de iterar sin usar un rango. Hay dos formas Los comentarios al final del código muestran cuál sería la versión del rango (suponiendo que el tamaño del incremento sea 1).
Adelante
Hacia atrás
Cambiar el tamaño de incremento a le
-1
permite retroceder.Tenga en cuenta la
to
y lathrough
diferencia.zancada: elementos de SequenceType
Adelante por incrementos de 2
Estoy usando
2
en este ejemplo solo para mostrar otra posibilidad.Hacia atrás
Notas
@matt tiene una solución interesante donde define su propio operador inverso y lo llama
>>>
. No se necesita mucho código para definir y se usa así:Echa un vistazo a C-Style para bucles eliminados de Swift 3
fuente
Swift 4 en adelante
fuente
Con Swift 5, de acuerdo con sus necesidades, puede elegir uno de los siguientes cuatro ejemplos de código de Playground para resolver su problema.
# 1 Utilizando el
ClosedRange
reversed()
métodoClosedRange
tiene un método llamadoreversed()
.reversed()
El método tiene la siguiente declaración:Uso:
Como alternativa, puede usar el
Range
reversed()
método:# 2 Usando la
sequence(first:next:)
funciónSwift Standard Library proporciona una función llamada
sequence(first:next:)
.sequence(first:next:)
tiene la siguiente declaración:Uso:
# 3 Usando la
stride(from:through:by:)
funciónSwift Standard Library proporciona una función llamada
stride(from:through:by:)
.stride(from:through:by:)
tiene la siguiente declaración:Uso:
Como alternativa, puede usar
stride(from:to:by:)
:# 4. Usando
AnyIterator
init(_:)
inicializadorAnyIterator
tiene un inicializador llamadainit(_:)
.init(_:)
tiene la siguiente declaración:Uso:
Si es necesario, puede refactorizar el código anterior creando un método de extensión
Int
y envolviendo su iterador en él:fuente
Para Swift 2.0 y superior, debe aplicar el reverso en una colección de rango
Se ha renombrado a .reversed () en Swift 3.0
fuente
En Swift 4 y posterior
fuente
Swift 4.0
Si desea incluir el
to
valor:fuente
Si uno quiere iterar a través de una matriz (
Array
o más generalmente cualquieraSequenceType
) a la inversa. Tienes algunas opciones adicionales.Primero puede hacer
reverse()
la matriz y recorrerla de manera normal. Sin embargo, prefiero usar la mayorenumerate()
parte del tiempo, ya que genera una tupla que contiene el objeto y su índice.Lo único a tener en cuenta aquí es que es importante llamarlos en el orden correcto:
for (index, element) in array.enumerate().reverse()
produce índices en orden descendente (que es lo que generalmente espero). mientras:
for (index, element) in array.reverse().enumerate()
(que es una coincidencia más cercana a la de NSArrayreverseEnumerator
)recorre la matriz hacia atrás pero genera índices ascendentes.
fuente
En cuanto a Swift 2.2, Xcode 7.3 (10 de junio de 2016):
Salida:
fuente
Puede considerar usar el
while
bucle C-Style en su lugar. Esto funciona bien en Swift 3:fuente
Puede usar el método reverse () para invertir fácilmente los valores.
El método reverse () invierte los valores.
fuente
fuente