Quand j'utilise la boucle for dans Playground, tout a bien fonctionné, jusqu'à ce que j'ai changé le premier paramètre de la boucle pour être la valeur la plus élevée. (itéré dans l'ordre décroissant)
Est-ce un bug? Est-ce que quelqu'un d'autre l'a eu?
for index in 510..509 { var a = 10 }
Le countur qui affiche le nombre d'itérations qui seront exécutées continue à cocher …
Xcode 6 beta 4 ajoute deux fonctions pour itérer sur les plages avec une étape autre que one: ssortingde(from: to: by:)
, qui est utilisé avec des plages exclusives et ssortingde(from: through: by:)
, qui est utilisé avec inclusive gammes.
Pour parcourir une plage dans l'ordre inverse, ils peuvent être utilisés comme suit:
for index in ssortingde(from: 5, to: 1, by: -1) { print(index) } //prints 5, 4, 3, 2 for index in ssortingde(from: 5, through: 1, by: -1) { print(index) } //prints 5, 4, 3, 2, 1
Notez que ni l'une ni l'autre n'est une fonction membre Range
. Ce sont des fonctions globales qui returnnent une SsortingdeTo
ou SsortingdeThrough
, qui sont définies différemment de la structure Range
.
Une version précédente de cette réponse utilisait la fonction membre by()
de la structure Range
, qui a été supprimée en version bêta 4. Si vous voulez voir comment cela a fonctionné, vérifiez l'historique des modifications.
Appliquez la fonction inverse à la plage pour revenir en arrière:
Pour Swift 1.2 et plus tôt:
// Print 10 through 1 for i in reverse(1...10) { println(i) }
Il fonctionne également avec des plages semi-ouvertes:
// Print 9 through 1 for i in reverse(1..<10) { println(i) }
Note: reverse(1...10)
crée un tableau de type [Int]
, donc bien que cela puisse convenir aux petites plages, il serait sage d'utiliser lazy
comme indiqué ci-dessous ou de considérer la réponse de ssortingde
acceptée si votre range est large .
Pour éviter de créer un grand tableau, utilisez lazy
avec reverse()
. Le test suivant s'exécute efficacement dans un Playground montrant qu'il ne crée pas un tableau avec un billion d' Int
!
Tester:
var count = 0 for i in lazy(1...1_000_000_000_000).reverse() { if ++count > 5 { break } println(i) }
Pour Swift 2.0 en Xcode 7:
for i in (1...10).reverse() { print(i) }
Notez que dans Swift 2.0, (1...1_000_000_000_000).reverse()
est de type ReverseRandomAccessCollection<(Range<Int>)>
, cela fonctionne donc bien:
var count = 0 for i in (1...1_000_000_000_000).reverse() { count += 1 if count > 5 { break } print(i) }
Pour Swift 3.0 reverse()
a été renommé en reversed()
:
for i in (1...10).reversed() { print(i) // prints 10 through 1 }
Mise à jour pour Swift 3
La réponse ci-dessous est un résumé des options disponibles. Choisissez celui qui correspond le mieux à vos besoins.
reversed
: nombres dans une plage Vers l'avant
for index in 0..<5 { print(index) } // 0 // 1 // 2 // 3 // 4
Vers l'arrière
for index in (0..<5).reversed() { print(index) } // 4 // 3 // 2 // 1 // 0
reversed
: éléments dans SequenceType
let animals = ["horse", "cow", "camel", "sheep", "goat"]
Vers l'avant
for animal in animals { print(animal) } // horse // cow // camel // sheep // goat
Vers l'arrière
for animal in animals.reversed() { print(animal) } // goat // sheep // camel // cow // horse
reversed
: éléments avec un index Parfois, un index est nécessaire lors de l'itération à travers une collection. Pour cela, vous pouvez utiliser enumerate()
, qui returnne un tuple. Le premier élément du tuple est l'index et le second élément est l'object.
let animals = ["horse", "cow", "camel", "sheep", "goat"]
Vers l'avant
for (index, animal) in animals.enumerated() { print("\(index), \(animal)") } // 0, horse // 1, cow // 2, camel // 3, sheep // 4, goat
Vers l'arrière
for (index, animal) in animals.enumerated().reversed() { print("\(index), \(animal)") } // 4, goat // 3, sheep // 2, camel // 1, cow // 0, horse
Notez que comme Ben Lachman l'a noté dans sa réponse , vous voudrez probablement faire .enumerated().reversed()
plutôt que .reversed().enumerated()
(ce qui augmenterait le nombre d'index).
La foulée est un moyen d'itérer sans utiliser de plage. Il y a deux forms. Les commentaires à la fin du code montrent ce que serait la version de la gamme (en supposant que la taille de l'incrément est 1).
startIndex.ssortingde(to: endIndex, by: incrementSize) // startIndex..<endIndex startIndex.ssortingde(through: endIndex, by: incrementSize) // startIndex...endIndex
Vers l'avant
for index in ssortingde(from: 0, to: 5, by: 1) { print(index) } // 0 // 1 // 2 // 3 // 4
Vers l'arrière
Changer la taille de l'incrément à -1
vous permet de revenir en arrière.
for index in ssortingde(from: 4, through: 0, by: -1) { print(index) } // 4 // 3 // 2 // 1 // 0
Notez la différence to
et à through
.
Transférer par incréments de 2
let animals = ["horse", "cow", "camel", "sheep", "goat"]
J'utilise 2
dans cet exemple juste pour montrer une autre possibilité.
for index in ssortingde(from: 0, to: 5, by: 2) { print("\(index), \(animals[index])") } // 0, horse // 2, camel // 4, goat
Vers l'arrière
for index in ssortingde(from: 4, through: 0, by: -1) { print("\(index), \(animals[index])") } // 0, horse // 1, cow // 2, camel // 3, sheep // 4, goat
@matt a une solution intéressante où il définit son propre opérateur inverse et l'appelle >>>
. Il ne prend pas beaucoup de code à définir et est utilisé comme ceci:
for index in 5>>>0 { print(index) } // 4 // 3 // 2 // 1 // 0
Découvrez sur C-Style For Loops Supprimé de Swift 3
Swift 4 à partir de
for i in ssortingde(from: 5, to: 0, by: -1) { print(i) } //prints 5, 4, 3, 2, 1 for i in ssortingde(from: 5, through: 0, by: -1) { print(i) } //prints 5, 4, 3, 2, 1, 0
Pour Swift 2.0 et supérieur, vous devez appliquer le reverse sur une collection de gamme
for i in (0 ..< 10).reverse() { // process }
Il a été renommé .reversed () dans Swift 3.0
Avec Swift 3, selon vos besoins, vous pouvez choisir l'une des huit implémentations de code Playground suivantes afin de résoudre votre problème.
CountableClosedRange
reversed()
CountableClosedRange
a une méthode appelée reversed()
. reversed()
méthode reversed()
a la déclaration suivante:
func reversed() -> ReversedRandomAccessCollection<CountableClosedRange<Bound>>
Renvoie une vue présentant les éléments de la collection dans l'ordre inverse.
Usage:
let reversedRandomAccessCollection = (0 ... 5).reversed() for index in reversedRandomAccessCollection { print(index) } /* Prints: 5 4 3 2 1 0 */
CountableRange
reversed()
CountableRange
a une méthode appelée reversed()
. reversed()
méthode reversed()
a la déclaration suivante:
func reversed() -> ReversedRandomAccessCollection<CountableRange<Bound>>
Renvoie une vue présentant les éléments de la collection dans l'ordre inverse.
Usage:
let reversedRandomAccessCollection = (0 ..< 6).reversed() for index in reversedRandomAccessCollection { print(index) } /* Prints: 5 4 3 2 1 0 */
sequence(first:next:)
La bibliothèque standard de Swift fournit une fonction appelée sequence(first:next:)
. sequence(first:next:)
a la déclaration suivante:
func sequence<T>(first: T, next: @escaping (T) -> T?) -> UnfoldSequence<T, (T?, Bool)>
Renvoie une séquence formée à partir des
first
applications paresseuses répétées denext
.
Usage:
let unfoldSequence = sequence(first: 5, next: { $0 - 1 >= 0 ? $0 - 1 : nil }) for index in unfoldSequence { print(index) } /* Prints: 5 4 3 2 1 0 */
ssortingde(from:through:by:)
La bibliothèque standard de Swift fournit une fonction appelée ssortingde(from:through:by:)
. ssortingde(from:through:by:)
a la déclaration suivante:
func ssortingde<T>(from start: T, through end: T, by ssortingde: T.Ssortingde) -> SsortingdeThrough<T> where T : Ssortingdeable
Retourne la séquence de valeurs
(self, self + ssortingde, self + 2 * ssortingde, … last)
où last est la dernière valeur de la progression inférieure ou égale àend
.
Usage:
let sequence = ssortingde(from: 5, through: 0, by: -1) for index in sequence { print(index) } /* Prints: 5 4 3 2 1 0 */
ssortingde(from:to:by:)
Swift Standard Library fournit une fonction appelée ssortingde(from:to:by:)
. ssortingde(from:to:by:)
a la déclaration suivante:
func ssortingde<T>(from start: T, to end: T, by ssortingde: T.Ssortingde) -> SsortingdeTo<T> where T : Ssortingdeable
Renvoie la séquence de valeurs
(self, self + ssortingde, self + 2 * ssortingde, … last)
où last est la dernière valeur de la progression qui est inférieure àend
.
Usage:
let sequence = ssortingde(from: 5, to: -1, by: -1) for index in sequence { print(index) } /* Prints: 5 4 3 2 1 0 */
init(_:)
AnyIterator
init(_:)
AnyIterator
a un initialiseur appelé init(_:)
. init(_:)
a la déclaration suivante:
init<I>(_ base: I) where I : IteratorProtocol, I.Element == Element
Crée un iterator qui enveloppe un iterator de base mais dont le type dépend uniquement du type d'élément de l'iterator de base.
Usage:
var index = 5 guard index >= 0 else { fatalError("index must be positive or equal to zero") } let iterator = AnyIterator<Int>({ defer { index = index - 1 } return index >= 0 ? index : nil }) for index in iterator { print(index) } /* Prints: 5 4 3 2 1 0 */
init(_:)
AnyIterator
init(_:)
AnyIterator
a un initialiseur appelé init(_:)
. init(_:)
a la déclaration suivante:
init(_ body: @escaping () -> AnyIterator.Element?)
Crée un iterator qui enveloppe la fermeture donnée dans sa méthode
next()
.
Usage:
var index = 5 guard index >= 0 else { fatalError("index must be positive or equal to zero") } let iterator = AnyIterator({ () -> Int? in defer { index = index - 1 } return index >= 0 ? index : nil }) for index in iterator { print(index) } /* Prints: 5 4 3 2 1 0 */
Int
personnalisée Vous pouvez refactoriser le code précédent en créant une méthode d'extension pour Int
et en y incluant votre iterator:
extension Int { func iterateDownTo(_ endIndex: Int) -> AnyIterator<Int> { var index = self guard index >= endIndex else { fatalError("self must be greater than or equal to endIndex") } let iterator = AnyIterator { () -> Int? in defer { index = index - 1 } return index >= endIndex ? index : nil } return iterator } } let iterator = 5.iterateDownTo(0) for index in iterator { print(index) } /* Prints: 5 4 3 2 1 0 */
Si l'on veut parcourir à travers un tableau ( Array
ou plus généralement tout SequenceType
) à l'envers. Vous avez quelques options supplémentaires.
D'abord, vous pouvez reverse()
le tableau et le parcourir comme d'habitude. Cependant je préfère utiliser enumerate()
plupart du time car il sort un tuple contenant l'object et son index.
La seule chose à noter ici est qu'il est important de les appeler dans le bon ordre:
for (index, element) in array.enumerate().reverse()
donne des indices dans l'ordre décroissant (ce que j'attends généralement). tandis que:
for (index, element) in array.reverse().enumerate()
(qui correspond plus à reverseEnumerator
de NSArray)
marche vers l'arrière mais produit des index ascendants.
quant à Swift 2.2, Xcode 7.3 (10 juin 2016):
for (index,number) in (0...10).enumerate() { print("index \(index) , number \(number)") } for (index,number) in (0...10).reverse().enumerate() { print("index \(index) , number \(number)") }
Sortie:
index 0 , number 0 index 1 , number 1 index 2 , number 2 index 3 , number 3 index 4 , number 4 index 5 , number 5 index 6 , number 6 index 7 , number 7 index 8 , number 8 index 9 , number 9 index 10 , number 10 index 0 , number 10 index 1 , number 9 index 2 , number 8 index 3 , number 7 index 4 , number 6 index 5 , number 5 index 6 , number 4 index 7 , number 3 index 8 , number 2 index 9 , number 1 index 10 , number 0
Swift 4.0
for i in ssortingde(from: 5, to: 0, by: -1) { print(i) // 5,4,3,2,1 }
Si vous voulez inclure la valeur to
:
for i in ssortingde(from: 5, through: 0, by: -1) { print(i) // 5,4,3,2,1,0 }
var sum1 = 0 for i in 0...100{ sum1 += i } print (sum1) for i in (10...100).reverse(){ sum1 /= i } print(sum1)
Vous pouvez envisager d'utiliser la boucle C-Style while à la place. Cela fonctionne très bien dans Swift 3:
var i = 5 while i > 0 { print(i) i -= 1 }