Swift Programming
Array Manipulation
Swift Indexing
Swift Language
Swift Development

New Array from Index Range Swift

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

In Swift, taking a range from an array does not automatically produce a brand-new Array. It usually produces an ArraySlice, which is a lightweight view into part of the original collection. That distinction is the reason many answers feel incomplete: the slicing syntax is simple, but the return type is not always the final type you want. If you need a real [T], convert the slice explicitly with Array(...).

Basic Slice Syntax

Suppose you start with:

swift
let numbers = [10, 20, 30, 40, 50]

You can select a range like this:

swift
let slice = numbers[1..<4]
print(slice)

This gives the values 20, 30, 40, but the type is ArraySlice<Int>, not [Int].

That is often fine if you only need to iterate over a subsection temporarily.

Create a Real New Array

If you want an actual standalone array, wrap the slice.

swift
let numbers = [10, 20, 30, 40, 50]
let newArray = Array(numbers[1..<4])
print(newArray)

Now newArray is a true [Int].

This is the usual answer when an API specifically expects [T] rather than a slice, or when you want to store the result independently of the original array.

Open, Closed, and Partial Ranges

Swift supports several range forms.

Half-open range:

swift
let a = Array(numbers[1..<4])

Closed range:

swift
let b = Array(numbers[1...3])

Partial ranges:

swift
let prefixPart = Array(numbers[..<3])
let suffixPart = Array(numbers[2...])

The half-open form is especially common because it matches Swift's general indexing style and avoids off-by-one confusion.

Why ArraySlice Exists

Swift returns ArraySlice to avoid copying more than necessary. That is usually a performance win because a slice can reuse storage from the original array rather than allocate new storage immediately.

That leads to a practical rule:

  • keep the slice if you only need a lightweight view
  • convert to Array if you need an independent array value

Once you understand that design choice, the API feels much more predictable.

When APIs Force the Conversion

Some APIs accept any collection-like type, but many function signatures specifically require [T].

swift
1func process(_ values: [Int]) {
2    print(values.count)
3}
4
5let values = [1, 2, 3, 4, 5]
6process(Array(values[1..<4]))

This is a common reason to build a new array from a range: the slice itself is correct semantically, but the receiving API wants a concrete array.

Bounds Checking Still Matters

Swift is memory-safe, but invalid index ranges still cause a runtime trap.

swift
let bad = Array(numbers[1..<10])

If the range is dynamic, validate it first.

swift
1func subarray<T>(_ array: [T], from start: Int, to end: Int) -> [T]? {
2    guard start >= 0, end <= array.count, start <= end else {
3        return nil
4    }
5    return Array(array[start..<end])
6}
7
8print(subarray(numbers, from: 1, to: 4) ?? [])

This is the safer approach when the indices come from user input or another computation.

Common Pitfalls

The biggest mistake is assuming array[start..<end] already returns [T]. It usually returns ArraySlice<T>.

Another mistake is mixing up half-open and closed ranges and accidentally including one extra element or excluding the last one.

A third issue is creating dynamic ranges without checking bounds first.

Summary

  • Slicing an array with a range usually returns ArraySlice, not automatically a new Array
  • Use Array(array[start..<end]) when you explicitly need a fresh [T]
  • Swift supports half-open, closed, and partial ranges for slicing
  • Keep ArraySlice when you want a lightweight view and avoid unnecessary copying
  • Validate dynamic ranges before slicing to avoid runtime traps

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.