假设在映射数组时调用了一个函数,该函数返回一个Result
。例如:
func parseFeedItem(_ object: Any) -> Result<FeedItem, Error> {...}
func parseFeed(_ root: Any) -> Result<Feed, Error> {
...
let items = objects.compactMap { parseFeedItem($0) }
...
}
映射的结果(上面的items
(将是Result
s的数组;"联合";的结果,即Result
作为其中之一:
- 具有值数组的
success
,如果数组中的所有Result
s都是success
es;或 - CCD_ 8与阵列中第一个CCD_
基本上,我想出了:
typealias Results<T, E> = Result<[T], E> where E: Error
let r: Results<FeedItem, Error> = items.reduce(.success([FeedItem]())) { (accumulator, result) -> Results<FeedItem, Error> in
switch accumulator {
case .failure(_):
return accumulator
case .success(let array):
switch result {
case .failure(let error):
return .failure(error)
case .success(let value):
var newArray = array
newArray.append(value)
return .success(newArray)
}
}
}
例如,如果仅使用success
es:运行
let items: [Result<FeedItem, Error>] = [
.success(FeedItem(1)),
.success(FeedItem(2)),
.success(FeedItem(3)),
]
... run `reduce` defined above ...
print(r) // .success([FeedItem(1), FeedItem(2), FeedItem(3)])
如果数组至少包含一个failure
,如:
let items: [Result<FeedItem, Error>] = [
.success(FeedItem(1)),
.success(FeedItem(2)),
.failure(MyError.blah),
]
... run `reduce` defined above ...
print(r) // .failure(MyError.blah)
所以这是有效的。然而,问题是:
- 有更短的方法吗
- 它是否具有性能,即是否有任何方法可以改进
有一种较短且通用的方法可以实现这一点。Result类型有两个非常有用的方法:map((和flatMap((,请参阅链接的Apple文档以了解它们的确切工作方式。
使用它们,我构建了一个通用函数,允许您在Result中封装的类型之间执行自定义操作,如果操作的两个成员都是成功的,或者第一次遇到错误时失败,则给出.success(和操作的结果(:
func resultOperation<T, E: Error>(_ lhs: Result<T, E>, _ rhs: Result<T, E>, _ operation: ((T, T) -> T)) -> Result<T, E> {
lhs.flatMap { (lhsValue) -> Result<T, E> in
rhs.map { (rhsValue) -> T in
return operation(lhsValue, rhsValue)
}
}
}
在您的情况下,运算参数将是+运算符,它将两个数组的元素添加到一个数组中。代码看起来像:
let r: Results<FeedItem, Error> = items.reduce(.success([FeedItem]())) { resultOperation($0, $1, +) }