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!

Enjoy the article? Join over 20,000+ Swift developers and enthusiasts who get my weekly updates.