Swift Non-Nil Values In An Array Of Optionals

原文:https://useyourloaf.com/blog/swift-non-nil-values-in-an-array-of-optionals/

我发现除了配合我们超级熟悉的 switch语句,很难想起有别的地方使用 case语句,这里有个很有用的案例,当你需要对可选的数组中非空值做一些操作时。

这是一个使用场景,一个String类型的数组,里面有一些值可能为nil

1
let names = ["Tom", nil, "Fred"]

names的类型是 [String?], 一个可选的字符串数组,假设我想对数组里每一个非空的值做一些操作:

1
2
3
func doSomething(_ name: String) {
print(name)
}

这个doSomething函数的参数是一个非可选的String类型. 可以通过if let语句遍历数组获取non-nil值 :

1
2
3
4
5
for name in names {
if let name = name { doSomething(name) }
}
// Tom
// Fred

这是记住flatMap高阶函数跳过nil值的好时机:

1
2
3
4
5
for name in names.flatMap({ $0 }) {
doSomething(name)
}
// Tom
// Fred

这个方法是不差,但我喜欢用case语句与可选项匹配的方式:

1
2
3
4
5
for case let name? in names {
doSomething(name)
}
// Tom
// Fred

enum 有两个语句:.none.some(T)。上面例子可选项(let name?) 是一个简写,用于匹配 .some。我们也可以用.some来写:

1
2
3
for case .some(let name) in names {
doSomething(name)
}

匹配 nil 元素的范式可以这样写:

1
2
3
for case .none in names {
print("found nil")
}

你可以用 ? 范式来匹配可选项中的特定值

1
2
3
for case "Fred"? in names {
print("Found Fred")
}

使用 where 和 case

你可以更进一步,添加一个where子句作为数组的过滤器。

1
2
3
4
5
6
7
let scores = [1,5,8,3,10,nil,7]
for case let score? in scores where score > 6 {
print(score)
}
// 8
// 10
// 7

在执行过滤操作之前,我更喜欢使用flatMap删除nil值,

1
2
3
for score in scores.flatMap({ $0 }).filter({ $0 > 6 }) {
print(score)
}

推荐阅读

Swift Guide to Map Filter Reduce