How to get the first N elements of array in Swift

⋅ 5 min read ⋅ Swift Array

Table of Contents

You can easily support sarunw.com by checking out this sponsor.

Sponsor sarunw.com and reach thousands of iOS developers.

Using subscript with range

Swift offers several range operators to work with the array subscript(_:). Let's say we want to retrieve the first three elements from an array. We can do that in a variety form of range operators.

Closed Range Operator

let names = ["Anna", "Alex", "Brian", "Jack"]
let arraySlice = names[0...2]
// ["Anna", "Alex", "Brian"]


Closed Range Operator with One-Sided Ranges

let names = ["Anna", "Alex", "Brian", "Jack"]
let arraySlice = names[...2]
// ["Anna", "Alex", "Brian"]


Half-Open Range Operator

let names = ["Anna", "Alex", "Brian", "Jack"]
let arraySlice = names[0..<3]
// ["Anna", "Alex", "Brian"]


Half-Open Range Operator with One-Sided Ranges

let names = ["Anna", "Alex", "Brian", "Jack"]
let arraySlice = names[..<3]
// ["Anna", "Alex", "Brian"]

All of the above examples produce the same ArraySlice of the first three items of names array. It is up to your preference to choose which form of range operator you want. I prefer a half-open range operator (0..<3) since it contains a number of elements that I want (3) to get in the range operator.

Caveats

You might get an "Array index is out of range" error if your range is larger than an array. So, make sure your array is larger than the range or use other methods if an array size can't be determined at compile time.

let names = ["Anna", "Alex", "Brian", "Jack"]
let arraySlice = names[..<5]
// Array index is out of range

Using prefix(_:)

prefix(_:) will return a subsequence, up to the specified maximum length. So if we want the first n items, we use .prefix(n).

let names = ["Anna", "Alex", "Brian", "Jack"]
let arraySlice = names.prefix(3)
// ["Anna", "Alex", "Brian"]

The great thing about this method is that you don't have to worry about indexes out of ranges like the previous example.

func prefix(_ maxLength: Int) -> ArraySlice

Since the parameter of this method is maxLength. If the maximum length exceeds the number of elements in the collection, the result contains all the elements in the collection.

We can safely use this on a collection regardless of its size.

let names = ["Anna", "Alex", "Brian", "Jack"]
let arraySlice = names.prefix(5)
// ["Anna", "Alex", "Brian", "Jack"]

Using prefix(upTo:) and prefix(through:)

prefix(upTo:) is equivalent to using a partial half-open range as the collection’s subscript. So, the following example is equivalent to names[..<3].

let names = ["Anna", "Alex", "Brian", "Jack"]
let arraySlice = names.prefix(upTo: 3)
// ["Anna", "Alex", "Brian"]

There is also prefix(through:), which equivalent to using a partial closed range (names[...2]).

let names = ["Anna", "Alex", "Brian", "Jack"]
let arraySlice = names.prefix(through: 2)
// ["Anna", "Alex", "Brian"]

Caveats

Apple discourages to use them. You might want to use subscript notation instead.

Apple clearly states this in the documentation pages.

Using the prefix(upTo:) method is equivalent to using a partial half-open range as the collection’s subscript. The subscript notation is preferred over prefix(upTo:).

Using the prefix(through:) method is equivalent to using a partial closed range as the collection’s subscript. The subscript notation is preferred over prefix(through:).

And since it is equivalent to subscript form, you will get the same "Array index is out of range" if your index is larger than an array. So, these methods don't add any benefit over the subscript notation.

let names = ["Anna", "Alex", "Brian", "Jack"]
let arraySlice = names.prefix(upTo: 5)
// Array index is out of range

ArraySlice

One thing to keep in mind when using all of the above methods is, the result of them is ArraySlice. There are two things you should know about ArraySlice.

1. Slices Are Views onto Arrays

The ArraySlice type is used as a way for us to perform operations on a subset of a larger array, which means to be fast and memory-efficient. The ArraySlice instance presents a view onto the storage of a larger array without allocating any new storage of their own.

For this reason, long-term storage of ArraySlice instances is discouraged. A slice holds a reference to the entire storage of a larger array, not just to the portion it presents, even after the original array’s lifetime ends. Long-term storage of a slice may therefore prolong the lifetime of elements that are no longer otherwise accessible, which can appear to be memory and object leakage.

If you plan to store the array slice result, please create a new array to hold that.

let names = ["Anna", "Alex", "Brian", "Jack"]
let arraySlice = names.prefix(3)
let firstThreeNames = Array(arraySlice)

2. Slices Maintain Indices of an original array

Slices maintain the same indices of the larger array for the same elements. Unlike an array, ArraySlice may have a nonzero startIndex and an endIndex that is not equal to count since it uses the same indices of the original array.

The following example gets a slice of elements index 1 and 2 from the names array. As you can see, the index of "Alex" and "Brain" is not 0 and 1 but maintain the same indices of 1 and 2.

let names = ["Anna", "Alex", "Brian", "Jack"]
let arraySlice = names[1...2]
// ["Alex", "Brian"]
arraySlice.firstIndex(of: "Alex") // 1
arraySlice.firstIndex(of: "Brian") // 2

This might not affect our case since we try to get first N elements, but it is good to know this, so you don't blindly assume index from the ArraySlice.

You can easily support sarunw.com by checking out this sponsor.

Sponsor sarunw.com and reach thousands of iOS developers.
Read more article about Swift, 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 Share
Previous
UIStackView padding

Learn how to add padding to your stack view's content.

Next
How expensive is DateFormatter

If you are working on iOS for long enough, there is a chance that you might have known that DateFormatter is expensive, but what is costly about DateFormatter? Let's find out in this article.

← Home