swift - 在 Swift 中减少 Result 数组
问题描述
假设在映射数组时调用了一个函数,并且该函数返回一个Result
. 例如:
func parseFeedItem(_ object: Any) -> Result<FeedItem, Error> {...}
func parseFeed(_ root: Any) -> Result<Feed, Error> {
...
let items = objects.compactMap { parseFeedItem($0) }
...
}
映射(items
上图)的结果将是一个 s 数组Result
。理想情况下,在此之后,我们想知道结果的“联合”,即Result
:
success
带有值的数组,如果数组中的所有Result
s 都是success
es;或者failure
failure
与数组中第一个的错误。
基本上,我想出了:
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, +) }
推荐阅读
- html - 如何进行 2 个链式转换,第一个带有转换,接下来没有转换?
- python - 如何通过使用python将现有值移动到下一个索引来在特定索引中的现有列表中插入值
- java - Autowire 静态接口对象 - Spring Boot 2.0
- python - tkinter 窗口在被破坏后不会消失
- c# - 如何将文件列的值传递给 ILNumerics 3D 图形?
- python-3.x - 如何在pyspark中使用其他Rdd元素的所有可能组合创建新Rdd?
- python - 如何从Python的excel中的不同位置写入多个单元格
- java - 如何动态声明实例变量?
- c# - 通过 ASP.NET CORE WEB API 并发请求和共享 HttpClient
- mysql - 选择 MySQL 中的所有记录,除非记录存在于另一个表中