swift for loop: para index, elemento em array?

Existe uma function que eu possa usar para iterar em uma matriz e ter índice e elemento, como o enumerado do python?

for index, element in enumerate(list): ... 

Sim. A partir do Swift 3.0, se você precisar do índice para cada elemento junto com seu valor, poderá usar o método enumerated() para iterar o array. Ele retorna uma seqüência de pares composta do índice e o valor de cada item na matriz. Por exemplo:

 for (index, element) in list.enumerated() { print("Item \(index): \(element)") } 

Antes do Swift 3.0 e depois do Swift 2.0, a function era chamada de enumerate() :

 for (index, element) in list.enumerate() { print("Item \(index): \(element)") } 

Antes do Swift 2.0, enumerate era uma function global.

 for (index, element) in enumerate(list) { println("Item \(index): \(element)") } 

O Swift 3 fornece um método chamado enumerated() para Array . enumerated() tem a seguinte declaração:

 func enumerated() -> EnumeratedSequence> 

Retorna uma seqüência de pares (n, x), onde n representa um inteiro consecutivo começando em zero, e x representa um elemento da seqüência.


Nos casos mais simples, você pode usar enumerated() com um loop for. Por exemplo:

 let list = ["Car", "Bike", "Plane", "Boat"] for (index, element) in list.enumerate() { print(index, ":", element) } /* prints: 0 : Car 1 : Bike 2 : Plane 3 : Boat */ 

Observe, no entanto, que você não está limitado a usar enumerated() com um loop for. Na verdade, se você planeja usar enumerated() com um loop for para algo semelhante ao código a seguir, você está fazendo errado:

 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)] 

A maneira correta de fazer isso é:

 let list = [Int](1...5) let arrayOfTuples = Array(list.enumerated()) print(arrayOfTuples) // prints [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)] 

Como alternativa, você também pode usar enumerated() com 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]] 

Além disso, embora tenha algumas limitações , forEach pode ser um bom substituto para um loop for:

 let list = [Int](1...5) list.reversed().enumerated().forEach { print($0, ":", $1) } /* prints: 0 : 5 1 : 4 2 : 3 3 : 2 4 : 1 */ 

Usando enumerated() e makeIterator() , você pode até mesmo iterar manualmente em seu Array . Por exemplo:

 import UIKit class ViewController: UIViewController { var generator = ["Car", "Bike", "Plane", "Boat"].enumerated().makeIterator() // Link this IBAction to a UIButton in your storyboard @IBAction func iterate(_ sender: UIButton) { let tuple: (offset: Int, element: String)? = generator.next() print(String(describing: tuple)) } } /* Will print the following lines for 6 `touch up inside`: Optional((0, "Car")) Optional((1, "Bike")) Optional((2, "Plane")) Optional((3, "Boat")) nil nil */ 

Começando com o Swift 2, a function enumerate precisa ser chamada na coleção da seguinte forma:

 for (index, element) in list.enumerate() { print("Item \(index): \(element)") } 

Eu encontrei esta resposta enquanto procurava uma maneira de fazer isso com um dictionary , e acontece que é muito fácil adaptá-lo, apenas passe uma tupla para o elemento.

 // Swift 2 var list = ["a": 1, "b": 2] for (index, (letter, value)) in list.enumerate() { print("Item \(index): \(letter) \(value)") } 

Enumeração básica

 for (index, element) in arrayOfValues.enumerate() { // do something useful } 

ou com o Swift 3 …

 for (index, element) in arrayOfValues.enumerated() { // do something useful } 

Enumerar, Filtrar e Mapear

No entanto, na maioria das vezes, uso enumerar em combinação com mapa ou filtro. Por exemplo, ao operar em alguns arrays.

Neste array eu queria filtrar elementos ímpares ou mesmo indexados e convertê-los de Ints para Doubles. Então, enumerate() obtém o índice e o elemento, depois o filtro verifica o índice e, finalmente, para se livrar da tupla resultante, eu o mapeio apenas para o elemento.

 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) }) 

Começando com o Swift 3, é

 for (index, element) in list.enumerated() { print("Item \(index): \(element)") } 

Esta é a fórmula do loop de enumeração:

 for (index, value) in shoppingList.enumerate() { print("Item \(index + 1): \(value)") } 

Para mais detalhes, você pode verificar aqui .

Usando .enumerate() funciona, mas não fornece o índice verdadeiro do elemento; ele fornece apenas um Int começando com 0 e incrementando em 1 para cada elemento sucessivo. Isso geralmente é irrelevante, mas existe o potencial de comportamento inesperado quando usado com o tipo ArraySlice . Tome o seguinte código:

 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 

É um exemplo um pouco inventado, e não é um problema comum na prática, mas ainda assim acho que vale a pena saber que isso pode acontecer.

Xcode 8 e Swift 3: Array podem ser enumerados usando tempArray.enumerate ()

Exemplo:

 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 

Você pode simplesmente usar o loop de enumeração para obter o resultado desejado:

Swift 2:

 for (index, element) in elements.enumerate() { print("\(index): \(element)") } 

Swift 3 e 4:

 for (index, element) in elements.enumerated() { print("\(index): \(element)") } 

Ou você pode simplesmente passar por um loop para obter o mesmo resultado:

 for index in 0.. 

Espero que ajude.

Para aqueles que querem usar forEach .

Swift 4

 extension Array { func forEachWithIndex(_ body: (Int, Element) throws -> Void) rethrows { try zip((startIndex ..< endIndex), self).forEach(body) } } 

Ou

 array.enumerated().forEach { ... } 

Eu pessoalmente prefiro usar o método forEach :

 list.enumerated().forEach { (index, element) in ... } 

Você também pode usar a versão curta:

 list.enumerated().forEach { print("index: \($0.0), value: \($0.1)") }