Compare integers, dates, strings, and more
Most folks realize Swift’s ranges are powerful, but not enough people realize just how powerful they are - and how completely natural they can be to use.
Let’s start off with the basics. You can create a closed range like this:
let startNumber = 10
let endNumber = 100
let numberRange = startNumber...endNumber
That range is a data type just like any other, so it has methods you can use. For example, you can query whether a number lies inside the range like this:
if numberRange.contains(50) {
print("Number is inside the range")
} else {
print("Number is outside the range")
}
Querying range bounds like this is so common that Swift even has its own dedicated operator, ~=
. It means “contains”, and it lets you use a shorter syntax if you want:
if numberRange ~= 50 {
print("Number is inside the range")
} else {
print("Number is outside the range")
}
Personally I prefer using contains()
because it reads much more naturally, but the ~=
operator has the advantage that it can be used without parentheses, like this:
if 10...100 ~= 50 {
print("Number is inside the range")
}
To do that using contains()
isn’t particularly beautiful:
if (10...100).contains(50) {
print("Number is inside the range")
}
So far these are just regular ranges that most folks use all the time. To take things up a notch, let’s look at date ranges: you can specify a start and end date, then check whether other dates lie inside that range.
This works the same way as using integers. Start by creating a range:
let startDate = Date().addingTimeInterval(-1000)
let endDate = Date().addingTimeInterval(1000)
let dateRange = startDate...endDate
Next, pick out a test date:
let testDate = Date()
Now use contains()
to figure out whether the test date lies inside the range:
if dateRange.contains(testDate) {
print("Inside the range")
}
You can use the ~=
operator here too:
if dateRange ~= testDate {
print("Inside the range")
}
Even strings get in on this range action. So, we could define a range of strings to contain all animals that start with A through M like this:
let startAnimal = "aardvark"
let endAnimal = "mule"
let animalsAThroughM = startAnimal...endAnimal
You can then check if other animals lie inside that range like this:
if animalsAThroughM.contains("giraffe") {
print("Giraffes are in the range!")
}
This behavior isn’t magic – it’s just a side effect of these types conforming to the Comparable
protocol. This protocol is what allows you to compare integers, strings, and dates like this:
1 < 5
"abc" < "def"
firstDate < lastDate
This means if your own types also conform to Comparable
they can be used as ranges too. For example, here’s a simple User
struct that conforms to Comparable
by comparing its lone property:
struct User: Comparable {
var name: String
static func < (lhs: User, rhs: User) -> Bool {
return lhs.name < rhs.name
}
}
We can use that to create ranges by creating two instances and combining them into a range:
let adele = User(name: "Adele")
let taylor = User(name: "Taylor")
let userRange = adele...taylor
Now we can create a test object and check whether it lies inside the range:
let paul = User(name: "Paul")
if userRange.contains(paul) {
print("Paul is in!")
}
Because the paul
instance compares as greater than adele
but less than taylor
, Swift considers it part of the range.
As you’ve seen, ranges are powerful in Swift partly because they can be used with several important built-in types, but also because you can use them with your own types just by conforming to Comparable
!
SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until September 29th.
Sponsor Hacking with Swift and reach the world's largest Swift community!
Link copied to your pasteboard.