Skip to content

Instantly share code, notes, and snippets.

@MahdiBM
Created November 5, 2021 02:34
Show Gist options
  • Save MahdiBM/57f4aada183326a6679a76bff9fef8eb to your computer and use it in GitHub Desktop.
Save MahdiBM/57f4aada183326a6679a76bff9fef8eb to your computer and use it in GitHub Desktop.
Swift async/await: Async and Concurrent maps
extension Sequence {
/// Maps through the elements one by one,
/// executing the closure for each of them one at a time.
func asyncMap<T>(
_ closure: @Sendable (Element) async throws -> T
) async rethrows -> [T] {
var array: [T] = []
array.reserveCapacity(self.underestimatedCount)
for element in self {
array.append(try await closure(element))
}
return array
}
/// Maps through the elements concurrently,
/// executing the closure for all the elements at the same time.
/// Keeps the order of the elements with the help of the id.
func concurrentMap<T, ID>(
id identifyingClosure: (Element) -> ID,
_ closure: @escaping @Sendable (Element) async throws -> T
) async rethrows -> [T] where ID: Equatable {
try await withThrowingTaskGroup(of: (value: T, id: ID).self) { group in
let withIdentifiers = self.map({ (element: $0, id: identifyingClosure($0)) })
for (element, id) in withIdentifiers {
group.addTask {
try await (value: closure(element), id: id)
}
}
var array: [(value: T, id: ID)] = []
array.reserveCapacity(self.underestimatedCount)
for try await valueWithId in group {
array.append(valueWithId)
}
array.sort(by: { lhs, rhs in
withIdentifiers.firstIndex(where: { $0.id == lhs.id })! <
withIdentifiers.firstIndex(where: { $0.id == rhs.id })!
})
return array.map(\.value)
}
}
}
extension Sequence where Element: Equatable {
/// Maps through the elements concurrently,
/// executing the closure for all the elements at the same time.
/// Keeps the order of the elements.
func concurrentMap<T>(
_ closure: @escaping @Sendable (Element) async throws -> T
) async rethrows -> [T] {
try await self.concurrentMap(id: { $0 }, closure)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment