Swift 2: “for… in” filtering
While looking through slides for What’s New in Swift again, I’ve decided to instead play around with and write down the new Swift 2 idioms here for easy reference for myself (and hopefully others). This post focusses on the “for… in” filtering:
The Concept
The idea behind “for… in” filtering is that now you can do filters inline vs in your for loop. So instead of this:
let numbers = [1,2,3,4,5,6,7,8,9,10]
// BS2 (Before Swift 2)
for number in numbers {
if number % 2 == 0 {
print(number)
}
}
You can now do this!
let numbers = [1,2,3,4,5,6,7,8,9,10]
// Swift 2
for number in numbers where number % 2 == 0 {
print(number)
}
“for… in” + Pattern Matching
Note that you can use the pattern matching with “if case” in combination with the for…in filtering for some even more advanced filtering! Here is one example:
let taylorSwiftAlbumsWithYear = [
("Red", 2014),
("1989", 2014),
("Fearless", 2008),
("Speak Now", 2008)]
for case let (album, 2014) in taylorSwiftAlbumsWithYear {
print("Taylor Swift's album \(album) was released in 2014")
}
// printed:
// Taylor Swift's album Red was released in 2014
// Taylor Swift's album 1989 was released in 2014
Filtering with Enum
Finally, you can filter enum values like this:
enum MyEnum {
case MyEnumCase(String)
case MyOtherEnumCase(String)
}
let enumValues = [MyEnum.MyEnumCase("someValue"),
MyEnum.MyEnumCase("someOtherValue"),
MyEnum.MyOtherEnumCase("NatashaTheRobot was here")]
for case let .MyEnumCase(value) in enumValues {
print(value)
}
// someValue
// someOtherValue
Note here that the let outside the enum case refers to the value inside 🙁 I hope the Swift team updates this syntax to be what they had in their slides:
// MORE READABLE IMO, BUT DOES NOT WORK
for case .MyEnumCase(let value) in enumValues {
print(value)
}
Filtering Optionals
An implication of filtering of enum values is that you can now filter Optionals:
let numbersWithOptions: [Int?] = [nil, 1,2,4, nil, 6]
for case let .Some(number) in numbersWithOptions where number % 2 == 0 {
print(number)
}
But of course you should use the version using the new shorthand syntax for .Some(let number):
let numbersWithOptions: [Int?] = [nil, 1,2,4, nil, 6]
for case let number? in numbersWithOptions where number % 2 == 0 {
print(number)
}
// 2,4,6
If you’re confused by the ? in theAnswer?, see my blog post on the new unwrapping optionals with pattern matching.
This still doesn’t feel natural to me. I’ll have to look back on this blog post a few times as I’m refactoring my code for Swift 2!