Swift
programming
range
developer
tutorial

How to create range in Swift?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Ranges are one of the most common small language features in Swift because they show up in loops, slicing, pattern matching, and collection APIs. The important part is not just memorizing the operators, but understanding which bounds are included and which APIs expect a closed, half-open, or one-sided range.

Closed and Half-Open Ranges

Swift has two standard range operators for bounded ranges.

A closed range includes both endpoints:

swift
let closed = 1...5
print(closed.contains(1))
print(closed.contains(5))

A half-open range includes the lower bound and excludes the upper bound:

swift
let halfOpen = 1..<5
print(halfOpen.contains(1))
print(halfOpen.contains(5))

This distinction matters in loops. A half-open range is especially useful with counts and indices because the upper bound is often the element count.

swift
for index in 0..<3 {
    print(index)
}

That prints 0, 1, and 2.

Create One-Sided Ranges

Swift also supports one-sided ranges. These are often used for slicing collections rather than standalone numeric iteration.

Examples:

swift
1let numbers = [10, 20, 30, 40, 50]
2
3let prefixSlice = numbers[..<3]
4let suffixSlice = numbers[2...]
5let inclusivePrefix = numbers[...2]
6
7print(prefixSlice)
8print(suffixSlice)
9print(inclusivePrefix)

The semantics are:

  • '..<n means everything before n'
  • '...n means everything through n'
  • 'n... means everything from n onward'

These are especially convenient when you do not want to calculate both bounds manually.

Use Ranges with Arrays and Strings Carefully

Ranges are heavily used for collection slicing, but not every collection behaves like an integer-indexed array.

For arrays, integer indices work directly:

swift
let letters = ["a", "b", "c", "d", "e"]
let middle = letters[1..<4]
print(middle)

Strings are different because Swift strings are collections of grapheme clusters, not random-access arrays of bytes. That means you use String.Index rather than integer offsets.

swift
1let text = "Swift"
2let start = text.startIndex
3let end = text.index(start, offsetBy: 3)
4let part = text[start..<end]
5print(part)

That is a range too, but the bounds are string indices rather than plain integers.

Create a Range Value Explicitly

You can store a range in a variable and pass it around just like other values.

swift
1let pageRange: ClosedRange<Int> = 1...10
2let apiWindow: Range<Int> = 0..<50
3
4print(pageRange.contains(7))
5print(apiWindow.contains(50))

This can be useful when a function should accept a range parameter:

swift
1func sum(valuesIn range: ClosedRange<Int>) -> Int {
2    var total = 0
3    for value in range {
4        total += value
5    }
6    return total
7}
8
9print(sum(valuesIn: 1...4))

Use stride When You Need Steps

A normal range does not let you specify a step size. For that, use stride.

swift
for value in stride(from: 0, to: 10, by: 2) {
    print(value)
}

If you want the end included when possible, use through instead of to:

swift
for value in stride(from: 0, through: 10, by: 2) {
    print(value)
}

This is an important distinction because many developers initially expect 0...10 to have a built-in step parameter. Swift separates range creation from stepped iteration.

Ranges in Conditions and Pattern Matching

Ranges also work in switch cases and boolean membership checks.

swift
1let score = 87
2
3switch score {
4case 90...100:
5    print("A")
6case 80..<90:
7    print("B")
8default:
9    print("Other")
10}

This is a clean way to express intervals without chaining multiple comparisons.

Common Pitfalls

The most common mistake is confusing ... with ..< and accidentally including or excluding the upper bound. Another is using integer offsets directly with strings, which does not match Swift’s string indexing model. Developers also sometimes try to use a range when they really need a stepped sequence, which means stride is the correct tool. A final issue is forgetting that array slices are views over a range of the original collection, not automatically brand-new arrays unless explicitly converted.

Summary

  • Use a...b for a closed range and a..<b for a half-open range.
  • One-sided ranges are useful for slicing collections.
  • Arrays use integer indices, but strings use String.Index values.
  • Use stride when you need stepped iteration rather than a plain range.
  • Ranges are useful beyond loops, including slicing, validation, and pattern matching.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

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

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.