tutorial the programming objective language curso apple ios swift

ios - the - Reemplazo para el bucle de estilo C en Swift 2.2



the swift programming language pdf (4)

Swift 2.2 desaprobó el bucle de estilo C. Sin embargo, en algunos casos, el nuevo operador de rango simplemente no funciona igual.

for var i = 0; i < -1; ++i { ... }

y

for i in 0..<-1 { ... }

La última fallará en tiempo de ejecución. Puedo envolver el bucle con un if , pero está un poco desordenado. A veces este tipo de bucle es útil.

¿Alguna idea?

Casos de uso

  1. Debe enumerar todos los elementos de una matriz, excepto el último.
  2. Debe enumerar todos los números enteros enteros en un rango decimal, pero el rango puede ser como [0.5, 0.9] y, por lo tanto, no hay enteros (después de algunas matemáticas), lo que da como resultado un bucle vacío.

Imitando el "bucle de estilo C"

No del todo bonito, pero puede ajustar el rango: s límite superior con un max(0, ..) para asegurarse de que nunca tome valores negativos.

let foo : [Int] = [] for i in 0..<max(0,foo.count-1) { print(i) }

Sin embargo, from.stride(to:by) la from.stride(to:by) (que ya se ha mencionado en las otras respuestas, ver, por ejemplo, la respuesta de Michael).

Sin embargo, creo que es valioso señalar explícitamente que from.stride(to:by) devuelve perfectamente un StrideTo vacío (o, si se convierte en una matriz: una matriz vacía) si intenta avanzar a un número menor que pero por un paso positivo. Por ejemplo, avanzar de 0 a -42 por 1 no intentará avanzar completamente a través de "∞ -> -∞ -> -42" (es decir, un caso de error), sino que simplemente devuelve un StrideTo vacío (como debería):

Array(0.stride(to: -42, by: 1)) // [] // -> equivalent to your C loop: for i in 0.stride(to: foo.count-1, by: 1) { print(i) }

Caso de uso 1: enumere todos menos el último elemento de una matriz

Para este caso de uso específico, una solución simple es usar dropLast() (como lo describe Sulthan en los comentarios a su pregunta) seguido de forEach .

let foo = Array(1...5) foo.dropLast().forEach { print($0) } // 1 2 3 4

O, si necesita más control sobre qué abandonar, aplique un filtro a su matriz

let foo = Array(1...5) foo.filter { $0 < foo.count }.forEach { print($0) } // 1 2 3 4

Caso de uso 2: enumere todos los enteros en un rango decimal, permitiendo que esta enumeración esté vacía

Para su ejemplo de intervalo decimal / doble intervalo cerrado ( [0.6, 0.9] ; un intervalo en lugar de un rango en el contexto de la sintaxis Swift), puede convertir el intervalo cerrado en un rango entero (usando la función forEach ) y aplicar un forEach sobre el último

let foo : (ClosedInterval<Double>) -> () = { (Int(ceil($0.start))..<Int(ceil($0.end))) .forEach { print($0) } } foo(0.5...1.9) // 1 foo(0.5...0.9) // nothing

O, si desea enumerar específicamente los (posibles) enteros contenidos en este intervalo; utilícelo como extensión adecuada para su propósito:

protocol MyDoubleBounds { func ceilToInt() -> Int } extension Double: MyDoubleBounds { func ceilToInt() -> Int { return Int(ceil(self)) // no integer bounds check in this simple example } } extension ClosedInterval where Bound: MyDoubleBounds { func enumerateIntegers() -> EnumerateSequence<(Range<Int>)> { return (self.start.ceilToInt() ..< self.end.ceilToInt()) .enumerate() } }

Ejemplo de uso:

for (i, intVal) in (1.3...3.2).enumerateIntegers() { print(i, intVal) } /* 0 2 1 3 */ for (i, intVal) in (0.6...0.9).enumerateIntegers() { print(i, intVal) } /* nothing */


Aunque no es tan "bonito", puedes usar stride :

for var i in 0.stride(to: -1, by: -1) { print(i) }


Como referencia: en Swift 3.0, la zancada ahora se define globalmente, lo que hace que el bucle se vea más natural:

for i in stride(from: 10, to: 0, by: -1){ print(i) } /* 10 9 8 7 6 5 4 3 2 1 */


Para Swift 3 y necesita cambiar el "índice"

for var index in stride(from: 0, to: 10, by: 1){}