// // 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(by keyPath: KeyPath) -> [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], 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] { sorted(using: descriptors, order: .ascending) } }