976

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):
    ...

20 Answers 20

1993

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)")
}
Sign up to request clarification or add additional context in comments.

7 Comments

Although it seems like a tuple, in Swift 1.2 - not sure about 2.0 - enumerate returns an EnumerateSequence<base: SequenceType> struct.
@Leviathlon noticeable or measurable performance overhead that will matter? No.
Maybe they'll change to the gerund, enumerating for Swift 4. Exciting!
@Honey for (index, element) in when using enumerated is misleading. should be for (offset, element) in
Do we hold a sweepstakes as to who can guess what it'll change to next. This damn language just can't sit still lol
|
163

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

1 Comment

Is getting access to the index the only benefit of using enumerate?
60

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

Comments

59

Swift 5.x:

let list = [0, 1, 2, 3, 4, 5]

list.enumerated().forEach { (index, value) in
    print("index: \(index), value: \(value)")
}

Or,

list.enumerated().forEach { 
    print("index: \($0.offset), value: \($0.element)")
} 

Or,

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

Comments

54

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

Comments

39

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

4 Comments

BTW you can implement enumeratedIndices by looping over with zip(self.indices, self)
@Alexander-ReinstateMonica for element in zip(indices, self) { try body(element) }. Btw I don't like the naming I chose, indexedElements might describe better what it does
Ooo I think that's a better name. Yeah, a for loop works, but also zip(self.indices, self) .forEach(body)
@Alexander-ReinstateMonica forEach does a for loop behind the scenes. I prefer to keep it plain 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) } } }
35

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

2 Comments

Interesting tidbit for forEach cannot return a value - Unexpected non-void return value in void function. So return the result afterwards.
You also won't be able to skip a loop if need be
25

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.

Comments

19

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

Comments

14

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.

3 Comments

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 Yes, that's why it's called enumerate. Also, slice is not array, so no surprise it behaves differently. There's no bug here - everything is by design. :)
True, but I never called it a bug. It just is potentially unexpected behavior that I thought was worth mentioning for those who didn't know how it could interact negatively with the ArraySlice type.
Are you aware of any way to get the index of the actual element - for example if using filter first?
12

Starting with Swift 3, it is

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

Comments

10

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.

Comments

7

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 { ... }

Comments

7

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

Comments

7

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 Comment

enumerated() was the magic spell I was looking for.... that fixed my 'uple pattern cannot match values of non-tuple type 'Items'' error.. THANK YOU!
6

Use .enumerated() like this in functional programming:

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

Comments

6

In iOS 8.0/Swift 4.0+

You can use forEach As per the Apple docs:

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

let numberWords = ["one", "two", "three"]

numberWords.enumerated().forEach { (key, value) in
   print("Key: \(key) - Value: \(value)")
}

Comments

5

If you for whatever reason want a more traditional looking for loop that accesses the elements in the array using their index:

let xs = ["A", "B", "C", "D"]

for i in 0 ..< xs.count {
    print("\(i) - \(xs[i])")
}

Output:

0 - A
1 - B
2 - C
3 - D

Comments

1

It's critical to note that Apple now does guarantee that the order is "correct"

https://developer.apple.com/documentation/swift/array/foreach(_:)

"Calls the given closure on each element in the sequence in the same order as a for-in loop" (Apple doco).

.enumerated().forEach { print("\($0.offset) \($0.element)") } 

Comments

-1

We called enumerate function to implements this. like

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.