What is Swift Range Expressions?
Different Types Of Range Operators
A range is a series of values between two numeric intervals. Range instance can be created using the range operator. Swift includes several range operators, which are shortcuts for expressing a range of values. Range operators can include or exclude the upper range, start the range with some value or can end before some max value. Ranges in Swift allow us to select parts of Strings, collections, and other types.
The
lowerBound
of the range instance in Swift is used to get the lowest value or the starting point of a range andupperBound
is used to get the highest value or the end point of a range.
ClosedRange
The ClosedRange operator (lower...upper
) defines a range that runs from lower
to upper
, and includes the values lower
and upper
. The closed range operator operates contains both it’s lower bound and upper bound.
for n in 3...5 {
print(n)
}
// Prints "3"
// Prints "4"
// Prints "5"
ClosedRange instance can be created by using the closed range operator (
...
). The closed range operator’s initial value should be less than or equal to the upper value else it will throw a run time error. Therefore ClosedRange instance cannot represent an empty range.
let arrInstance: ClosedRange<Int> = 0...5
print(arrInstance.contains(3))
// truelet zeroInclusive = 0...0
zeroInclusive.contains(0)
// true
zeroInclusive.isEmpty
// falselet arrInstance1: ClosedRange<Int> = 4...3
//Fatal error: Range requires lowerBound <= upperBound
ClosedRange and CountableClosedRange is approximately the same but in case of CountableClosedRange the bound you are specifying should conform to Strideable protocol and bound.stride should conform to SignedInteger that mean
CountableClosedRange
can create with Int bounds only.Even if we are iterate over a
Double
range in a for-in loop make use ofstride(from:to:by:)
orstride(from:through:by:)
in whichby:
parameter defines what factor we want to increment in each iteration.
Half-Open Range
The Half-Open Range operator (lower..<upper
) defines a range that runs from lower
to upper
, but it doesn’t include upper
.
for n in 3..<5 {
print(n)
}
// Prints "3"
// Prints "4"
Half-Open Range instance can be created by using the half-open range operator (
lower..<upper
). Half-Open Range instances can represent an empty interval, if both lower and upper values are same.
let arrInstance = 0..<5
print(arrInstance.contains(3))
// true
arrInstance.contains(6)
// falselet empty = 0..<0
empty.contains(0)
// false
empty.isEmpty
// true// in collection for n in 3..<3 {
print(n)
}
// Nothing will print as lower and upper values are same
One Sided Range
One-Sided Range operator has a value on only one side and another side contains elements up to infinite that is why it is called One-sided range. We can create One-sided range using either of the ...upper
, lower...
or the ..<upper
operator. Following are the different expressions for the One-sided range.
a) PartialRangeUpTo
PartialRangeUpTo instances are created by using the(..<upper
). PartialRangeUpTo instance can be used to check if a value is contained in a particular range of values.
let partialRangeUpTo = ..<5
partialRangeUpTo.contains(4)
// true
You can use a PartialRangeUpTo instance of a collection’s indices to represent the range from the start of the collection up to, but not including, the partial range’s upper bound.
let numbers = [10, 20, 30, 40, 50, 60, 70]
print(numbers[..<3])
// Prints "[10, 20, 30]"
b) PartialRangeThrough
PartialRangeThrough instances are created by using the prefix closed range operator (...upper
). PartialRangeThrough instance can be used to check if a value is contained in a particular range of values.
let partialRangeThrough = ...5
partialRangeThrough.contains(4)
// true
You can use a PartialRangeThrough instance of a collection’s indices to represent the range from the start of the collection up to, and including, the partial range’s upper bound.
let numbers = [10, 20, 30, 40, 50, 60, 70]
print(numbers[...3])
// Prints "[10, 20, 30, 40]"
c) PartialRangeFrom
PartialRangeFrom instances by using the postfix range operator (lower..
). You can use a partial range to quickly check if a value is contained in a particular range of values
let partialRangeFrom = 5...
partialRangeFrom.contains(4)
// falsepartialRangeFrom.contains(5)
// true
We can use a partial range of a collection’s indices to represent the range from the partial range’s lower bound up to the end of the collection.
let numbers = [10, 20, 30, 40, 50, 60, 70]
print(numbers[3...])
// Prints “[40, 50, 60, 70]”
PartialRangeFrom sequence counts upward indefinitely, so it is sugeested not use with methods that read the entire sequence before returning, such as
map(_:)
,filter(_:)
, orsuffix(_:)
. In other word, iterating over a PartialRangeFrom range requires to manually check where the loop should end otherwise it continue indefinitely and program can stuck.
All the above types of range operators can be used with loops if conditions, array iterations and even with switch case statements according to the use cases.
Things to remember
- The lower bound value must be smaller or equal to the upper bound value.
- The lower bound and upper bound values can be negative.
- We can iterate over range (excluding one-sided range) using for-in loops.
- We can use the range operator to access elements of an array and collections.
Thanks for reading, you can follow me on Medium for updated articles.
If you have any comments, questions, or recommendations feel free to post them in the comment section below! 👇 and please share and give claps 👏👏 if you liked this post.