映射Combine数组时如何避免嵌套闭包?
How to avoid nesting closures when mapping Combine arrays?
我有一个字符串数组,我想将其映射到不同的对象中。我正在使用 map 将数组转换为另一个数组,但它非常嵌套:
$favorites
.map { articleIDs in
articleIDs.compactMap { id in
state.articles.first { [=10=].id == id }
}
}
.assign(to: \Self.favorites, on: self)
.store(in: &cancellable)
是否有 shorthand 将转换应用于每个单独的项目?我本来想这样做,但没有成功:
state.$favorites
.mapEach { id in state.articles.first { [=11=].id == id } }
.assign(to: \Self.favorites, on: self)
.store(in: &cancellable)
这是一种方法,您:
- 使用
Publishers.Sequence
将单个数组转换为单个元素的管道
- 单独处理元素。
- 使用
collect
运算符将元素转换回数组。
这是一个您可以在 Xcode 操场上 运行 设计的示例:
import Combine
import UIKit
class MyStore: ObservableObject {
@Published var favorites: [(id: Int, title: String)] = []
let articles = [
(id: 22, title: "foo"),
(id: 5, title: "bar"),
(id: 13, title: "baz"),
]
var cancellable: Set<AnyCancellable> = []
func addFavorites(favorites: AnyPublisher<[Int], Never>) {
let articles = self.articles
favorites
.flatMap(Publishers.Sequence.init)
.compactMap { fav in articles.first { fav == [=10=].id }}
.collect()
.assign(to: \.favorites, on: self)
.store(in: &cancellable)
}
}
let store = MyStore()
store.addFavorites(favorites: Just([22, 13]).eraseToAnyPublisher())
print(store.favorites)
// => [(id: 22, title: "foo"), (id: 13, title: "baz")]
...但是我怀疑这实际上不是您想要的。一个更优雅的解决方案可能是创建一个定制的 compactMapEach
运算符。这是它的样子:
extension Publisher {
public func compactMapEach<T, U>(_ transform: @escaping (T) -> U?)
-> Publishers.Map<Self, [U]>
where Output == [T]
{
return map { [=11=].compactMap(transform) }
}
}
我有一个字符串数组,我想将其映射到不同的对象中。我正在使用 map 将数组转换为另一个数组,但它非常嵌套:
$favorites
.map { articleIDs in
articleIDs.compactMap { id in
state.articles.first { [=10=].id == id }
}
}
.assign(to: \Self.favorites, on: self)
.store(in: &cancellable)
是否有 shorthand 将转换应用于每个单独的项目?我本来想这样做,但没有成功:
state.$favorites
.mapEach { id in state.articles.first { [=11=].id == id } }
.assign(to: \Self.favorites, on: self)
.store(in: &cancellable)
这是一种方法,您:
- 使用
Publishers.Sequence
将单个数组转换为单个元素的管道
- 单独处理元素。
- 使用
collect
运算符将元素转换回数组。
这是一个您可以在 Xcode 操场上 运行 设计的示例:
import Combine
import UIKit
class MyStore: ObservableObject {
@Published var favorites: [(id: Int, title: String)] = []
let articles = [
(id: 22, title: "foo"),
(id: 5, title: "bar"),
(id: 13, title: "baz"),
]
var cancellable: Set<AnyCancellable> = []
func addFavorites(favorites: AnyPublisher<[Int], Never>) {
let articles = self.articles
favorites
.flatMap(Publishers.Sequence.init)
.compactMap { fav in articles.first { fav == [=10=].id }}
.collect()
.assign(to: \.favorites, on: self)
.store(in: &cancellable)
}
}
let store = MyStore()
store.addFavorites(favorites: Just([22, 13]).eraseToAnyPublisher())
print(store.favorites)
// => [(id: 22, title: "foo"), (id: 13, title: "baz")]
...但是我怀疑这实际上不是您想要的。一个更优雅的解决方案可能是创建一个定制的 compactMapEach
运算符。这是它的样子:
extension Publisher {
public func compactMapEach<T, U>(_ transform: @escaping (T) -> U?)
-> Publishers.Map<Self, [U]>
where Output == [T]
{
return map { [=11=].compactMap(transform) }
}
}