|
| 1 | +--- |
| 2 | +date: 2024-09-25 |
| 3 | +title: The Swift Ranges Cheatsheet |
| 4 | +slug: swift-ranges-cheatsheet |
| 5 | +images: [""] |
| 6 | +description: Ranges in Swift exlained, plain and simple. |
| 7 | +topics: [Swift, Ranges, Cheatsheet] |
| 8 | +--- |
| 9 | +# Swift Ranges Cheat Sheet |
| 10 | +Ranges are fantastic for when we want to work with a range of sorted values that contain no duplicates. |
| 11 | + |
| 12 | +## Core Concepts: |
| 13 | +- **Ranges** in Swift define a sequence of values between two bounds (lower and upper) and are widely used in loops, slicing collections, and pattern matching. |
| 14 | +- There are different types of ranges that control whether the bounds are included or excluded. |
| 15 | +- **Pattern Matching**: Ranges can be used in `switch` statements or `if` conditions to check if a value falls within a specific range. |
| 16 | +- **Comparable**: Ranges must hold a `Comparable` type. |
| 17 | +- Prefer ranges when you want to work with a **sequence of values** without storing the elements in memory, unlike an **array** that holds all its values. |
| 18 | + |
| 19 | +## Range Types Side by Side: |
| 20 | + |
| 21 | +| **Syntax** | **Range Type** | **Description** | **Lower Bound (✅/❌)** | **Upper Bound (✅/❌)** | **Includes Upper Bound (✅/❌)** | |
| 22 | +| -------------- | ------------------- | ----------------------------------------------------------------------- | ------------------------ | ------------------------ | ------------------------------ | |
| 23 | +| `a..<b` | `Range` | Half-open range; includes lower bound, excludes upper bound | ✅ | ✅ | ❌ | |
| 24 | +| `a...b` | `ClosedRange` | Closed range; includes both lower and upper bounds | ✅ | ✅ | ✅ | |
| 25 | +| `a...` | `PartialRangeFrom` | Range with only a lower bound | ✅ | ❌ | ❌ | |
| 26 | +| `...b` | `PartialRangeThrough`| Range with only an upper bound, includes upper bound | ❌ | ✅ | ✅ | |
| 27 | +| `..<b` | `PartialRangeUpTo` | Range with only an upper bound, excludes upper bound | ❌ | ✅ | ❌ | |
| 28 | +| `...` | `UnboundedRange` | Range without any bounds | ❌ | ❌ | ❌ | |
| 29 | + |
| 30 | +## Common Use Cases: |
| 31 | + |
| 32 | +### Iteration: |
| 33 | +```swift |
| 34 | +for i in 0..<5 { |
| 35 | + print(i) // Outputs 0 to 4 |
| 36 | +} |
| 37 | +``` |
| 38 | + |
| 39 | +### Pattern Matching: |
| 40 | +Ranges are great to use in `switch` or `if-case` conditions to check if a value lies in a range.[^1] |
| 41 | +```swift |
| 42 | +let number = 7 |
| 43 | +switch number { |
| 44 | + case 0..<5: print("0 to 4") |
| 45 | + case 5...10: print("5 to 10") |
| 46 | + default: print("Out of range") |
| 47 | +} |
| 48 | +``` |
| 49 | + |
| 50 | +[^1]: Notice how we need to use `default` instead of `case 18...` here. Swift `switch` is great because it requires us to handle every case, thus eliminating niche bugs. Unfortunately, Swift is not able to determine if we have handled every case. See: https://forums.swift.org/t/switch-on-int-with-exhaustive-cases-still-needs-default/49548 |
| 51 | + |
| 52 | +### Slicing |
| 53 | +By slicing a collection we can create a smaller "view" of that collection without actually needing to copy it. |
| 54 | + |
| 55 | +```swift |
| 56 | +let numbers = [10, 20, 30, 40, 50, 60] |
| 57 | + |
| 58 | +// Slice the array to get elements from index 1 to 3 (i.e., 20, 30, 40) |
| 59 | +let slice = numbers[1..<4] // ArraySlice<Int> |
| 60 | + |
| 61 | +print(slice) // Output: [20, 30, 40] |
| 62 | +``` |
| 63 | + |
| 64 | +Make sure you read [Sundell's article](https://www.swiftbysundell.com/articles/slicing-swift-collections/) on slicing! |
| 65 | + |
| 66 | +## Benefits Over Arrays: |
| 67 | +- **Memory Efficient**: Ranges don't store the values they represent, they just define the bounds. |
| 68 | +- **Performance**: Faster when iterating over numbers or intervals since there's no need to allocate memory for an entire sequence. |
| 69 | +- Use a **range** when you need to express a numeric interval without storing values in memory. |
| 70 | + - Arrays should be used when the actual values need to be accessed or manipulated. |
| 71 | + |
| 72 | +## Conclusion |
| 73 | +Ranges are a core part of Swift, used for efficient iteration, pattern matching, and controlling bounds in a concise and readable way. |
0 commit comments