Find every other element in an array with Swift

Published on: June 30, 2015
Updated on: April 23, 2024

There are times when you need to extract a subset of an array. For example, you might need to find all elements in an array at an odd index. Or maybe you need all items at an even index. In other words, you're looking for every "other" element in an array. This might seem like a non-trivial task and you may have tried this before using a for loop as follows:

var itemsAtEvenIndices = [Int]()
let allItems = [1, 2, 3, 4, 5, 6, 7]

var index = 0
for item in allItems {
  if index % 2 == 0 {
    itemsAtEvenIndices.append(item)
  }
  index += 1
}

This isn't a bad approach, but we can do better. A slightly nicer way would be to use the enumerated() method that is defined on Sequence:

var itemsAtEvenIndices = [Int]()
let allItems = [1, 2, 3, 4, 5, 6, 7]

for (index, item) in allItems.enumerated() {
  if index.isMultiple(of: 2) {
    itemsAtEvenIndices.append(item)
  }
}

This works and saves you some bookkeeping because you don't have to increment the index in every iteration of the loop but you still have to define a mutable array that you append items to. Let's take a look at one last way to extract all items at even indices without any mutable arrays and without unneeded bookkeeping:

let allItems = [1, 2, 3, 4, 5, 6, 7]
let itemsAtEvenIndices = allItems.enumerated().compactMap { tuple in
  tuple.offset.isMultiple(of: 2) ? tuple.element : nil
}

The code above uses compactMap to transform tuples of (offset: Int, element: Int) into an array of [Int]. Since compactMap filters out all nil values and only keeps the Int values, we can use a ternary statement that checks whether tuple.offset.isMultiple(of: 2) is true. If it is, we return tuple.element and if it isn't, we return nil. The end result is the same as the previous two examples except it's cleaner and doesn't involve any mutable state, or intermediate variables.

If you want to learn more about compactMap, check out the following post I wrote: When to use map, flatMap and compactMap. If you have any questions, feedback, or just want to get in touch. Don't hesitate to reach out to me on Twitter.

Special thanks to Bas Broek for pointing out that tuple.offset.isMultiple(of: 2) is maybe a bit nicer than tuple.offset % 2 == 0.

Expand your learning with my books

Practical Swift Concurrency header image

Learn everything you need to know about Swift Concurrency and how you can use it in your projects with Practical Swift Concurrency. It contains:

  • Eleven chapters worth of content.
  • Sample projects that use the code shown in the chapters.
  • Free updates for future iOS versions.

The book is available as a digital download for just $39.99!

Learn more