Réponses:
Oui. À partir de Swift 3.0, si vous avez besoin de l'index pour chaque élément avec sa valeur, vous pouvez utiliser la enumerated()
méthode pour parcourir le tableau. Il renvoie une séquence de paires composée de l'index et de la valeur de chaque élément du tableau. Par exemple:
for (index, element) in list.enumerated() {
print("Item \(index): \(element)")
}
Avant Swift 3.0 et après Swift 2.0, la fonction était appelée enumerate()
:
for (index, element) in list.enumerate() {
print("Item \(index): \(element)")
}
Avant Swift 2.0, enumerate
était une fonction mondiale.
for (index, element) in enumerate(list) {
println("Item \(index): \(element)")
}
enumerate
?
enumerating
pour Swift 4. Excitant!
for (index, element) in
lors de l'utilisation enumerated
est trompeur. devrait êtrefor (offset, element) in
Swift 5 fournit une méthode appelée enumerated()
pour Array
. enumerated()
a la déclaration suivante:
func enumerated() -> EnumeratedSequence<Array<Element>>
Renvoie une séquence de paires (n, x), où n représente un entier consécutif commençant à zéro et x représente un élément de la séquence.
Dans les cas les plus simples, vous pouvez utiliser enumerated()
une boucle for. Par exemple:
let list = ["Car", "Bike", "Plane", "Boat"]
for (index, element) in list.enumerated() {
print(index, ":", element)
}
/*
prints:
0 : Car
1 : Bike
2 : Plane
3 : Boat
*/
Notez cependant que vous n'êtes pas limité à une utilisation enumerated()
avec une boucle for. En fait, si vous prévoyez d'utiliser enumerated()
avec une boucle for pour quelque chose de similaire au code suivant, vous le faites mal:
let list = [Int](1...5)
var arrayOfTuples = [(Int, Int)]()
for (index, element) in list.enumerated() {
arrayOfTuples += [(index, element)]
}
print(arrayOfTuples) // prints [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
Une façon plus rapide de le faire est:
let list = [Int](1...5)
let arrayOfTuples = Array(list.enumerated())
print(arrayOfTuples) // prints [(offset: 0, element: 1), (offset: 1, element: 2), (offset: 2, element: 3), (offset: 3, element: 4), (offset: 4, element: 5)]
Comme alternative, vous pouvez également utiliser enumerated()
avec map
:
let list = [Int](1...5)
let arrayOfDictionaries = list.enumerated().map { (a, b) in return [a : b] }
print(arrayOfDictionaries) // prints [[0: 1], [1: 2], [2: 3], [3: 4], [4: 5]]
De plus, bien qu’il ait limites , il forEach
peut être un bon remplacement d'une boucle for:
let list = [Int](1...5)
list.reversed().enumerated().forEach { print($0, ":", $1) }
/*
prints:
0 : 5
1 : 4
2 : 3
3 : 2
4 : 1
*/
En utilisant enumerated()
et makeIterator()
, vous pouvez même itérer manuellement sur votre Array
. Par exemple:
import UIKit
import PlaygroundSupport
class ViewController: UIViewController {
var generator = ["Car", "Bike", "Plane", "Boat"].enumerated().makeIterator()
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(type: .system)
button.setTitle("Tap", for: .normal)
button.frame = CGRect(x: 100, y: 100, width: 100, height: 100)
button.addTarget(self, action: #selector(iterate(_:)), for: .touchUpInside)
view.addSubview(button)
}
@objc func iterate(_ sender: UIButton) {
let tuple = generator.next()
print(String(describing: tuple))
}
}
PlaygroundPage.current.liveView = ViewController()
/*
Optional((offset: 0, element: "Car"))
Optional((offset: 1, element: "Bike"))
Optional((offset: 2, element: "Plane"))
Optional((offset: 3, element: "Boat"))
nil
nil
nil
*/
enumerate
?
J'ai trouvé cette réponse en cherchant un moyen de le faire avec un dictionnaire , et il s'avère qu'il est assez facile de l'adapter, il suffit de passer un tuple pour l'élément.
// Swift 2
var list = ["a": 1, "b": 2]
for (index, (letter, value)) in list.enumerate() {
print("Item \(index): \(letter) \(value)")
}
Vous pouvez simplement utiliser une boucle d'énumération pour obtenir le résultat souhaité:
Swift 2:
for (index, element) in elements.enumerate() {
print("\(index): \(element)")
}
Swift 3 & 4:
for (index, element) in elements.enumerated() {
print("\(index): \(element)")
}
Ou vous pouvez simplement passer par une boucle for pour obtenir le même résultat:
for index in 0..<elements.count {
let element = elements[index]
print("\(index): \(element)")
}
J'espère que cela aide.
for (index, element) in arrayOfValues.enumerate() {
// do something useful
}
ou avec Swift 3 ...
for (index, element) in arrayOfValues.enumerated() {
// do something useful
}
Cependant, j'utilise le plus souvent enumerate en combinaison avec map ou filter. Par exemple, en opérant sur quelques tableaux.
Dans ce tableau, je voulais filtrer les éléments impairs ou même indexés et les convertir d'Ints en Doubles. Ainsi, enumerate()
vous obtenez l'index et l'élément, puis le filtre vérifie l'index, et enfin, pour me débarrasser du tuple résultant, je le mappe uniquement sur l'élément.
let evens = arrayOfValues.enumerate().filter({
(index: Int, element: Int) -> Bool in
return index % 2 == 0
}).map({ (_: Int, element: Int) -> Double in
return Double(element)
})
let odds = arrayOfValues.enumerate().filter({
(index: Int, element: Int) -> Bool in
return index % 2 != 0
}).map({ (_: Int, element: Int) -> Double in
return Double(element)
})
Utiliser des .enumerate()
œuvres, mais il ne fournit pas le véritable index de l'élément; il ne fournit qu'un Int commençant par 0 et incrémenté de 1 pour chaque élément successif. Cela n'est généralement pas pertinent, mais il existe un risque de comportement inattendu lorsqu'il est utilisé avec le ArraySlice
type. Prenez le code suivant:
let a = ["a", "b", "c", "d", "e"]
a.indices //=> 0..<5
let aSlice = a[1..<4] //=> ArraySlice with ["b", "c", "d"]
aSlice.indices //=> 1..<4
var test = [Int: String]()
for (index, element) in aSlice.enumerate() {
test[index] = element
}
test //=> [0: "b", 1: "c", 2: "d"] // indices presented as 0..<3, but they are actually 1..<4
test[0] == aSlice[0] // ERROR: out of bounds
C'est un exemple quelque peu artificiel, et ce n'est pas un problème courant dans la pratique, mais je pense que cela vaut la peine de savoir que cela peut se produire.
it does not actually provide the true index of the element; it only provides an Int beginning with 0 and incrementing by 1 for each successive element
Oui, c'est pourquoi cela s'appelle énumérer . De plus, la tranche n'est pas un tableau, donc pas surprenant qu'elle se comporte différemment. Il n'y a pas de bug ici - tout est par conception. :)
filter
premier?
Pour être complet, vous pouvez simplement parcourir vos indices de tableau et utiliser l'indice pour accéder à l'élément à l'index correspondant:
let list = [100,200,300,400,500]
for index in list.indices {
print("Element at:", index, " Value:", list[index])
}
Utilisation de forEach
list.indices.forEach {
print("Element at:", $0, " Value:", list[$0])
}
Utilisation de la enumerated()
méthode de collecte . Notez qu'il retourne une collection de tuples avec le offset
et le element
:
for item in list.enumerated() {
print("Element at:", item.offset, " Value:", item.element)
}
en utilisant forEach:
list.enumerated().forEach {
print("Element at:", $0.offset, " Value:", $0.element)
}
Ceux-ci imprimeront
Élément à: 0 Valeur: 100
Élément à: 1 Valeur: 200
Élément à: 2 Valeur: 300
Élément à: 3 Valeur: 400
Élément à: 4 Valeur: 500
Si vous avez besoin de l'index du tableau (pas du décalage) et de son élément, vous pouvez étendre Collection et créer votre propre méthode pour obtenir les éléments indexés:
extension Collection {
func indexedElements(body: ((index: Index, element: Element)) throws -> Void) rethrows {
var index = startIndex
for element in self {
try body((index,element))
formIndex(after: &index)
}
}
}
Une autre implémentation possible comme suggéré par Alex est de compresser les index de collection avec ses éléments:
extension Collection {
func indexedElements(body: ((index: Index, element: Element)) throws -> Void) rethrows {
for element in zip(indices, self) { try body(element) }
}
}
Essai:
let list = ["100","200","300","400","500"]
list.dropFirst(2).indexedElements {
print("Index:", $0.index, "Element:", $0.element)
}
Ce sera p [rint
Index: 2 Élément: 300
Index: 3 Élément: 400
Index: 4 Élément: 500
enumeratedIndices
en bouclant aveczip(self.indices, self)
for element in zip(indices, self) { try body(element) }
. Btw je n'aime pas le nom que j'ai choisi, indexedElements
pourrait mieux décrire ce qu'il fait
for
boucle fonctionne, mais aussizip(self.indices, self) .forEach(body)
forEach
fait une boucle for dans les coulisses. Je préfère rester simple et simple github.com/apple/swift/blob/master/stdlib/public/core/…@inlinable public func forEach( _ body: (Element) throws -> Void ) rethrows { for element in self { try body(element) } } }
Xcode 8 et Swift 3: les tableaux peuvent être énumérés à l'aide de tempArray.enumerated()
Exemple:
var someStrs = [String]()
someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]
for (index, item) in someStrs.enumerated()
{
print("Value at index = \(index) is \(item)").
}
console:
Value at index = 0 is Apple
Value at index = 1 is Amazon
Value at index = 2 is Google
Pour ceux qui veulent utiliser forEach
.
Swift 4
extension Array {
func forEachWithIndex(_ body: (Int, Element) throws -> Void) rethrows {
try zip((startIndex ..< endIndex), self).forEach(body)
}
}
Ou
array.enumerated().forEach { ... }
Pour ce que vous voulez faire, vous devez utiliser la enumerated()
méthode sur votre tableau :
for (index, element) in list.enumerated() {
print("\(index) - \(element)")
}
Nous avons appelé la fonction énumération pour implémenter ceci. comme
for (index, element) dans array.enumerate () {
// index est la position d'index du tableau
// l'élément est l'élément du tableau
}