You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
2.4 KiB
87 lines
2.4 KiB
//
|
|
// Sequence+Extensions.swift
|
|
// PadelClub
|
|
//
|
|
// Created by Razmig Sarkissian on 03/03/2024.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
extension Collection {
|
|
/// Returns the element at the specified index if it is within bounds, otherwise nil.
|
|
subscript (safe index: Index) -> Element? {
|
|
return indices.contains(index) ? self[index] : nil
|
|
}
|
|
}
|
|
|
|
extension Sequence {
|
|
func sorted<T: Comparable>(by keyPath: KeyPath<Element, T>) -> [Element] {
|
|
return sorted { a, b in
|
|
return a[keyPath: keyPath] < b[keyPath: keyPath]
|
|
}
|
|
}
|
|
}
|
|
|
|
extension Sequence {
|
|
func pairs() -> AnySequence<(Element, Element)> {
|
|
AnySequence(zip(self, self.dropFirst()))
|
|
}
|
|
}
|
|
|
|
extension Sequence {
|
|
func concurrentForEach(
|
|
_ operation: @escaping (Element) async throws -> Void
|
|
) async throws {
|
|
// A task group automatically waits for all of its
|
|
// sub-tasks to complete, while also performing those
|
|
// tasks in parallel:
|
|
try await withThrowingTaskGroup(of: Void.self) { group in
|
|
for element in self {
|
|
group.addTask {
|
|
try await operation(element)
|
|
}
|
|
|
|
for try await _ in group {}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
enum SortOrder {
|
|
case ascending
|
|
case descending
|
|
}
|
|
|
|
extension Sequence {
|
|
func sorted(using descriptors: [MySortDescriptor<Element>],
|
|
order: SortOrder) -> [Element] {
|
|
sorted { valueA, valueB in
|
|
for descriptor in descriptors {
|
|
let result = descriptor.comparator(valueA, valueB)
|
|
|
|
switch result {
|
|
case .orderedSame:
|
|
// Keep iterating if the two elements are equal,
|
|
// since that'll let the next descriptor determine
|
|
// the sort order:
|
|
break
|
|
case .orderedAscending:
|
|
return order == .ascending
|
|
case .orderedDescending:
|
|
return order == .descending
|
|
}
|
|
}
|
|
|
|
// If no descriptor was able to determine the sort
|
|
// order, we'll default to false (similar to when
|
|
// using the '<' operator with the built-in API):
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
extension Sequence {
|
|
func sorted(using descriptors: MySortDescriptor<Element>...) -> [Element] {
|
|
sorted(using: descriptors, order: .ascending)
|
|
}
|
|
}
|
|
|
|
|