在Swift中减少一个Result数组



假设在映射数组时调用了一个函数,该函数返回一个Result。例如:

func parseFeedItem(_ object: Any) -> Result<FeedItem, Error> {...}
func parseFeed(_ root: Any) -> Result<Feed, Error> {
...
let items = objects.compactMap { parseFeedItem($0) }
...
}

映射的结果(上面的items(将是Results的数组;"联合";的结果,即Result作为其中之一:

  • 具有值数组的success,如果数组中的所有Results都是successes;或
  • 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)
}
}
}

例如,如果仅使用successes:运行

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, +) }

相关内容

最新更新