Reputation: 98
It seems like there should be a "Swiftier" way to do this - but I'm still wrapping my head around the various ways to do pattern matching in Swift.
Suppose I have an Array of AnyObject and I'd like to loop through it and if the item is an Int AND the Int is a multiple of 5, then I'd like to print it out. Here's my initial approach that works:
let myStuff: [AnyObject] = [5, "dog", 11, 15, "cat"]
for item in myStuff {
if let myInt = item as? Int where myInt % 5 == 0 {
print ("\(item)")
}
}
Honestly, that's not bad...but with all of Swift's pattern matching syntax, it seems like I should be able to consolidate the logic to 1 line. So far, I haven't found an approach that works - but I was expecting to be able to do something like:
//This doesn't work, but I feel like something similar to this should
for item in myStuff where item is Int, item % 5 == 0 {
print ("\(item)")
}
Obviously, this isn't a huge deal - but it's more a thought exercise for me to understand Swift's pattern matching a little better.
Upvotes: 5
Views: 1228
Reputation: 80901
You can combine a pattern matching conditional cast with a where
clause like so:
let myStuff: [AnyObject] = [5, "dog", 11, 15, "cat"]
// item will be an Int, and divisible by 5
for case let item as Int in myStuff where item % 5 == 0 {
print(item)
}
// Prints:
// 5
// 15
Upvotes: 13
Reputation: 73196
@Hamish's neat solution is, imho, the "optimal" one, and the one to be accepted. But for the sake of the discussion, as an alternative the somewhat same logic can be applied with a chained functional approach:
let myStuff: [AnyObject] = [5, "dog", 11, 15, "cat"]
myStuff.flatMap{ $0 as? Int }.filter{ $0 % 5 == 0}.forEach {
print($0)
} /* 5 15 */
Upvotes: 7