How to get index and value from for loop in Swift
Table of Contents
Swift has many ways to iterate over a collection of items, e.g., forEach
and a for-in
loop.
You will get access to each element in the collection, but not an index.
If you also want to get an index of each element, there are two ways to do it.
Get index with indices property
indices
is an instance property of a Collection
protocol. It returns indices of that collection without an element, but you can easily use that index to get an element from the collection.
let names = ["Alice", "Bob", "John"]
// 1
names.indices.forEach { index in
// 2
print("\(index): \(names[index])")
}
// 0: Alice
// 1: Bob
// 2: John
// 3
for index in names.indices {
print("\(index): \(names[index])")
}
// 0: Alice
// 1: Bob
// 2: John
We can loops over indices
using forEach
1 or a for-in
3.
2 Then, you use that index
from indices
to get an element at that particular index, i.e., name[index]
.
You can easily support sarunw.com by checking out this sponsor.
AI Grammar: Correct grammar, spell check, check punctuation, and parphrase.
Get offset with enumerated method
Another way to get an index of an element in a collection is by using enumerated()
method.
enumerated()
returns a sequence of pairs (n, x)
, where:
n
represents a consecutive integerstarting at zero
.x
represents an element of the sequence.
We can access this index and element pairs by iterate over them using forEach
and a for-in
loop.
let names = ["Alice", "Bob", "John"]
names.enumerated().forEach { (index, name) in
print("\(index): \(name)")
}
// 0: Alice
// 1: Bob
// 2: John
for (index, name) in names.enumerated() {
print("\(index): \(name)")
}
// 0: Alice
// 1: Bob
// 2: John
Caveat
Iterating over index and element using the enumerated()
method sounds like a good choice. You get both index and element without a need to manually retrieve it like indices
, but there is one thing you should know before using it.
When you enumerate a collection, the integer part of each pair is a counter for the enumerationbut is not necessarily the index of the paired value.
You can think of enumerated()
doing something like this.
let names = ["Alice", "Bob", "John"]
var index = 0
for name in names {
print("\(index): \(name)")
index += 1
}
As you can see, the index
is just a counter, not an index. So, it can be used as indices only in instances of zero-based, integer-indexed collections.
Example
I can give you one example for non-zero-based indexed collections.
In this example, we use the dropFirst
method, which drops the first element from the collection. Then we use the result collection from dropFirst
method with enumerated()
and indices
.
let names = ["Alice", "Bob", "John"]
let dropFirstNames = names.dropFirst()
for (index, name) in dropFirstNames.enumerated() {
print("\(index): \(name)")
}
// 0: Bob
// 1: John
for index in dropFirstNames.indices {
print("\(index): \(names[index])")
}
// 1: Bob
// 2: John
As you can see, enumerated()
returns a counter of each element while indices
returns a real index of the resulting array[1].
Get index using zip and indices
If you want to iterate over the elements of a collection with its indices but don't want to get it manually, you can use the zip(_:_:)
function.
zip
creates a sequence of pairs built out of two underlying sequences.
We zip indices sequence (names.indices
) and names
together.
let names = ["Alice", "Bob", "John"]
let namesWithIndex = zip(names.indices, names)
let dropFirstNames = names.dropFirst()
let dropFirstNamesWithIndex = zip(dropFirstNames.indices, dropFirstNames)
for (index, name) in namesWithIndex {
print("\(index): \(name)")
}
// 0: Alice
// 1: Bob
// 2: John
for (index, name) in dropFirstNamesWithIndex {
print("\(index): \(name)")
}
// 1: Bob
// 2: John
You can easily support sarunw.com by checking out this sponsor.
AI Grammar: Correct grammar, spell check, check punctuation, and parphrase.
Conclusion
Array.enumerated()
might look like an easy choice when you want to get an index and element. But as you can see, it might not be what you are looking for if you want to use that index to reference an element in the collection since it is just a counter.
If you want to get an actual index of a collection, you must use indices
or indices
with zip
.
dropFirst
returnsArraySlice
.ArraySlice
maintain indices of the original array. This makes the starting index for anArraySlice
instance isn’t always zero. https://developer.apple.com/documentation/swift/arrayslice ↩︎
Read more article about Swift, Control Flow, Array, or see all available topic
Enjoy the read?
If you enjoy this article, you can subscribe to the weekly newsletter.
Every Friday, you'll get a quick recap of all articles and tips posted on this site. No strings attached. Unsubscribe anytime.
Feel free to follow me on Twitter and ask your questions related to this post. Thanks for reading and see you next time.
If you enjoy my writing, please check out my Patreon https://www.patreon.com/sarunw and become my supporter. Sharing the article is also greatly appreciated.
Become a patron Buy me a coffee Tweet ShareSwiftUI zIndex: Everything you need to know
zIndex is a modifier that controls the display order of overlapping views in SwiftUI. Let's learn how it works.
For loop in SwiftUI using ForEach
When creating an app, there is a time when you want to create a repetitive view or a collection of views from an array of data. We can do that in SwiftUI with ForEach.