Iterating Over an Array in Swift: Index and Element Under the Hood

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

How to get the index of an element when iterating over an array in Swift? Let's break down this popular question

\n\n

Imagine: you're writing in Swift and you want not just to go through an array, but also to know the position of each element. Whether you need to modify elements by index, compare adjacent values, or simply output a numbered list — the task is the same. The question "How to iterate a loop with index and element in Swift" has gathered thousands of views on Stack Overflow. This means this topic concerns many people.

\n\n

In this article, we won't just give a ready-made answer. We'll look under the hood: we'll break down what methods exist, which one is faster, which one is safer, and why one of them — enumerated() — has become the de facto standard. Let's go!

\n\n

The Problem: Why plain for-in doesn't work?

\n\n

Let's say you have an array of strings:

\n\n
let fruits = ["Apple", "Banana", "Cherry", "Melon"]
\n\n

The most obvious way is for-in:

\n\n
for fruit in fruits {\n    print(fruit)\n}
\n\n

This will print the names of the fruits. But what if you need to know the index? For example: "1. Apple, 2. Banana..."? A simple for-in doesn't provide the index. You have to resort to workarounds:

\n\n
var index = 0\nfor fruit in fruits {\n    print("\\(index). \\(fruit)")\n    index += 1\n}
\n\n

Does it work? Yes. Is it elegant? No. And what if the array is empty? What if you accidentally forget to increment index? Welcome to the world of bugs. Swift offers more elegant solutions.

\n\n

Method #1: The Classic — enumerated() method

\n\n

This is the most popular and recommended way. The enumerated() method returns a sequence of tuples (offset: Int, element: Element). Let's see how it works:

\n\n
for (index, fruit) in fruits.enumerated() {\n    print("\\(index + 1). \\(fruit)")\n}
\n\n

Output:

\n
1. Apple\n2. Banana\n3. Cherry\n4. Melon
\n\n

What happens under the hood?

\n\n

enumerated() does not create a new array. It returns a lazy sequence of type EnumeratedSequence. This means the elements are not copied into a new data structure — they are "wrapped" on the fly. Each time the next element is accessed, the sequence simply increments a counter and returns a tuple. This is very memory efficient, especially for large collections.

\n\n

An important nuance: offset always starts at 0. If you need an index starting from 1 (like in list numbering), simply add one. Swift doesn't do this for you — this is a conscious decision by the language developers to maintain consistency with array indexing.

\n\n

enumerated() with forEach

\n\n

The forEach method also supports enumerated():

\n\n
fruits.enumerated().forEach { (index, fruit) in\n    print("\\(index). \\(fruit)")\n}
\n\n

The difference between for-in and forEach is important: inside forEach, you cannot use break or continue. If you need to exit the loop early — use for-in.

\n\n

Method #2: Indexing via Range

\n\n

An old but still encountered way is to iterate over indices:

\n\n
for index in 0..<fruits.count {\n    print("\\(index). \\(fruits[index])")\n}
\n\n

It seems simple. But there are pitfalls:

\n\n
    \n
  • Safety: If the array changes during iteration (for example, in multithreaded code), fruits.count may become outdated, and you will go out of the array bounds.
  • \n
  • Readability: The code looks more "low-level". Other developers will spend an extra second to understand what you are doing.
  • \n
  • Performance: Accessing by index fruits[index] is an O(1) operation for arrays, but for other

Blogs

Book Recommendations