jellyflood/Shared/Extensions/Sequence.swift

79 lines
2.4 KiB
Swift

//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//
import Foundation
extension Sequence {
func compacted<Value>(using keyPath: KeyPath<Element, Value?>) -> [Element] {
filter { $0[keyPath: keyPath] != nil }
}
func first<V: Equatable>(property: (Element) -> V, equalTo value: V) -> Element? {
first { property($0) == value }
}
func intersection<Value: Equatable>(_ other: some Sequence<Value>, using keyPath: KeyPath<Element, Value>) -> [Element] {
filter { other.contains($0[keyPath: keyPath]) }
}
/// Returns the elements of the sequence, sorted by comparing values
/// at the given `KeyPath` of `Element`.
func sorted<Key: Comparable>(using keyPath: KeyPath<Element, Key>) -> [Element] {
sorted(by: { $0[keyPath: keyPath] < $1[keyPath: keyPath] })
}
// TODO: a flipped version of `sorted`
/// Returns the elements of the sequence, sorted by comparing values
/// at the given `KeyPath` of `Element`.
///
/// `nil` values are considered the maximum.
func sorted<Key: Comparable>(using keyPath: KeyPath<Element, Key?>) -> [Element] {
sorted {
let x = $0[keyPath: keyPath]
let y = $1[keyPath: keyPath]
if let x, let y {
return x < y
} else if let _ = x {
return true
} else if let _ = y {
return false
}
return true
}
}
func subtracting<Value: Equatable>(_ other: some Sequence<Value>, using keyPath: KeyPath<Element, Value>) -> [Element] {
filter { !other.contains($0[keyPath: keyPath]) }
}
func zipped<Value>(map mapToOther: (Element) throws -> Value) rethrows -> [(Element, Value)] {
try map { try ($0, mapToOther($0)) }
}
}
extension Sequence where Element: Equatable {
func first(equalTo other: Element) -> Element? {
first { $0 == other }
}
/// Returns an array containing the elements of the sequence that
/// are also within the given sequence.
func intersection(_ other: some Sequence<Element>) -> [Element] {
filter { other.contains($0) }
}
func subtracting(_ other: some Sequence<Element>) -> [Element] {
filter { !other.contains($0) }
}
}