Blog / October 11, 2024 / 4 mins read / By Mahi Garg

One Sided Range in Swift

Swift provides a powerful way to work with collections through ranges, which define a sequence of values with a start and an end. In addition to the traditional closed (...) and half-open (..<) ranges, Swift introduces one-sided ranges, a feature that makes working with sequences and collections more flexible and concise.

In this post, we’ll explore what one-sided ranges are, how to use them, and some practical examples to demonstrate their power.

What is a One-Sided Range?

In Swift, ranges typically have both a start and an end. However, there are scenarios where you might only care about one side of the range — either the starting point or the endpoint. That’s where one-sided ranges come in.

Types of One-Sided Ranges

There are two types of one-sided ranges in Swift:

  1. From a starting index to the end: start...
  2. From the beginning to an ending index: ...end

These ranges don’t require both a starting and an ending index, allowing you to specify only one side.

One-Sided Range Syntax

From a Starting Index to the End (start…)

The one-sided range start... starts at the specified start index and goes all the way to the end of the collection.

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let subset = numbers[3...] // Starts from index 3 to the end
print(subset)  // Output: [4, 5, 6, 7, 8, 9, 10]

In this example, 3... is a one-sided range that starts at index 3 (which is the number 4 in the numbers array) and goes to the end of the array.

From the Beginning to an Ending Index (…end)

The one-sided range ...end starts from the beginning of the collection and goes up to the specified end index.

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let subset = numbers[...4]  // Ends at index 4 (inclusive)
print(subset)  // Output: [1, 2, 3, 4, 5]

Here, the range ...4 means “from the beginning to index 4”, and it includes the value at index 4, which is the number 5.

Practical Examples of One-Sided Ranges

1. Slicing an Array

One-sided ranges are especially useful for slicing arrays. You can grab either the “tail” or “head” of an array in a very concise way.

let letters = ["a", "b", "c", "d", "e", "f", "g"]

// Extract the tail from index 3 to the end
let tail = letters[3...]
print(tail)  // Output: ["d", "e", "f", "g"]

// Extract the head from the beginning to index 2
let head = letters[...2]
print(head)  // Output: ["a", "b", "c"]

This approach is cleaner than using explicit ranges like 3..<letters.count or 0...2.

2. Using One-Sided Ranges with Strings

You can also use one-sided ranges with strings, which allows you to efficiently extract parts of the string.

let text = "Hello, Swift!"

// From the 7th character to the end
let substring = text[text.index(text.startIndex, offsetBy: 7)...]
print(substring)  // Output: "Swift!"

// From the beginning to the 5th character
let prefix = text[...text.index(text.startIndex, offsetBy: 4)]
print(prefix)  // Output: "Hello"

This allows you to work with strings in a way that doesn’t require you to manually compute the range.

3. Custom Ranges in Loops

One-sided ranges can also be used in loops, where you might want to iterate from or up to a certain point in a collection.

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

// Loop from index 2 to the end of the array
for number in numbers[2...] {
    print(number)
}
// Output:
// 30
// 40
// 50
// 60

This is a more readable way to iterate through a slice of a collection, compared to manually computing the range.

Combining One-Sided Ranges with Other Ranges

You can mix one-sided ranges with other ranges for even more flexibility. For example, combining a one-sided range with the prefix or suffix methods of a collection:

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// Use a one-sided range with prefix to get the first 4 elements
let firstFour = numbers.prefix(4)
print(firstFour)  // Output: [1, 2, 3, 4]

// Use a one-sided range with suffix to get the last 3 elements
let lastThree = numbers.suffix(3)
print(lastThree)  // Output: [8, 9, 10]

This helps create concise and readable code when working with array slices.

Benefits of One-Sided Ranges

  • Concise: One-sided ranges make code cleaner by removing the need to manually calculate indices or define both endpoints.
  • Expressive: They clearly express the intent to either “go from here to the end” or “from the start up to here”, improving code readability.
  • Flexible: One-sided ranges can be used across different types like arrays, strings, and even in loops.

Conclusion

One-sided ranges in Swift are a simple yet powerful tool that allows developers to work more effectively with sequences and collections. They provide cleaner syntax for slicing arrays, strings, and other collections, and are especially useful when you only need to define one side of a range.

By understanding how to use one-sided ranges, you can write more concise and expressive Swift code, reducing the complexity of index calculations and improving readability.

Comments