869
votes

Is there a function that I can use to iterate over an array and have both index and element, like Python's enumerate?

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

16 Answers

1819
votes

Yes. As of Swift 3.0, if you need the index for each element along with its value, you can use the enumerated() method to iterate over the array. It returns a sequence of pairs composed of the index and the value for each item in the array. For example:

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

Before Swift 3.0 and after Swift 2.0, the function was called enumerate():

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

Prior to Swift 2.0, enumerate was a global function.

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

Swift 5 provides a method called enumerated() for Array. enumerated() has the following declaration:

func enumerated() -> EnumeratedSequence<Array<Element>>

Returns a sequence of pairs (n, x), where n represents a consecutive integer starting at zero and x represents an element of the sequence.


In the simplest cases, you may use enumerated() with a for loop. For example:

let list = ["Car", "Bike", "Plane", "Boat"]
for (index, element) in list.enumerated() {
    print(index, ":", element)
}

/*
prints:
0 : Car
1 : Bike
2 : Plane
3 : Boat
*/

Note however that you're not limited to use enumerated() with a for loop. In fact, if you plan to use enumerated() with a for loop for something similar to the following code, you're doing it wrong:

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 swiftier way to do this is:

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

As an alternative, you may also use enumerated() with 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]]

Moreover, although it has some limitations, forEach can be a good replacement to a for loop:

let list = [Int](1...5)
list.reversed().enumerated().forEach { print($0, ":", $1) }

/*
prints:
0 : 5
1 : 4
2 : 3
3 : 2
4 : 1
*/

By using enumerated() and makeIterator(), you can even iterate manually on your Array. For example:

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
 */
54
votes

Starting with Swift 2, the enumerate function needs to be called on the collection like so:

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

I found this answer while looking for a way to do that with a Dictionary, and it turns out it's quite easy to adapt it, just pass a tuple for the element.

// Swift 2

var list = ["a": 1, "b": 2]

for (index, (letter, value)) in list.enumerate() {
    print("Item \(index): \(letter) \(value)")
}
19
votes

You can simply use loop of enumeration to get your desired result:

Swift 2:

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

Swift 3 & 4:

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

Or you can simply go through a for loop to get the same result:

for index in 0..<elements.count {
    let element = elements[index]
    print("\(index): \(element)")
}

Hope it helps.

19
votes

For completeness you can simply iterate over your array indices and use subscript to access the element at the corresponding index:

let list = [100,200,300,400,500]
for index in list.indices {
    print("Element at:", index, " Value:", list[index])
}

Using forEach

list.indices.forEach {
    print("Element at:", $0, " Value:", list[$0])
}

Using collection enumerated() method. Note that it returns a collection of tuples with the offset and the element:

for item in list.enumerated() {
    print("Element at:", item.offset, " Value:", item.element)
}

using forEach:

list.enumerated().forEach {
    print("Element at:", $0.offset, " Value:", $0.element)
}

Those will print

Element at: 0 Value: 100

Element at: 1 Value: 200

Element at: 2 Value: 300

Element at: 3 Value: 400

Element at: 4 Value: 500

If you need the array index (not the offset) and its element you can extend Collection and create your own method to get the indexed elements:

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

Another possible implementation as suggested by Alex is to zip the collection indices with its elements:

extension Collection {
    func indexedElements(body: ((index: Index, element: Element)) throws -> Void) rethrows {
        for element in zip(indices, self) { try body(element) }
    }
    var indexedElements: Zip2Sequence<Indices, Self> { zip(indices, self) }
}

Testing:

let list =  ["100","200","300","400","500"]

// You can iterate the index and its elements using a closure
list.dropFirst(2).indexedElements {
    print("Index:", $0.index, "Element:", $0.element)
}

// or using a for loop
for (index, element) in list.indexedElements  {
    print("Index:", index, "Element:", element)
}

This will p[rint

Index: 2 Element: 300

Index: 3 Element: 400

Index: 4 Element: 500

Index: 0 Element: 100

Index: 1 Element: 200

Index: 2 Element: 300

Index: 3 Element: 400

Index: 4 Element: 500

17
votes

Swift 5.x:

I personally prefer using the forEach method:

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

You can also use the short version:

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

Basic enumerate

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

or with Swift 3...

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

Enumerate, Filter and Map

However, I most often use enumerate in combination with map or filter. For example with operating on a couple of arrays.

In this array I wanted to filter odd or even indexed elements and convert them from Ints to Doubles. So enumerate() gets you index and the element, then filter checks the index, and finally to get rid of the resulting tuple I map it to just the element.

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

Using .enumerate() works, but it does not provide the true index of the element; it only provides an Int beginning with 0 and incrementing by 1 for each successive element. This is usually irrelevant, but there is the potential for unexpected behavior when used with the ArraySlice type. Take the following code:

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

It's a somewhat contrived example, and it's not a common issue in practice but still I think it's worth knowing this can happen.

9
votes

Starting with Swift 3, it is

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

This is the Formula of loop of Enumeration:

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

for more detail you can check Here.

4
votes

For those who want to use forEach.

Swift 4

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

Or

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

Xcode 8 and Swift 3: Array can be enumerated using tempArray.enumerated()

Example:

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
4
votes

For what you are wanting to do, you should use the enumerated() method on your Array:

for (index, element) in list.enumerated() {
    print("\(index) - \(element)")
}
1
votes

Use .enumerated() like this in functional programming:

list.enumerated().forEach { print($0.offset, $0.element) } 
-2
votes

We called enumerate function to implements this. like

    for (index, element) in array.enumerate() {
     index is indexposition of array
     element is element of array 
   }