@Thang Phi's answer has the right idea. This is not different, but it works with a level of abstraction that incorporates the "counted set" idea for which Swift doesn't yet provide a built-in type:
import OrderedCollections
public extension Sequence where Element: Hashable {
/// A version of this sequence without the earliest occurrences of all `elementsToRemove`.
///
/// If `elementsToRemove` contains multiple equivalent values,
/// that many of the earliest occurrences will be filtered out.
func filteringOutEarliestOccurrences(from elementsToRemove: some Sequence<Element>) -> some Sequence<Element> {
var elementCounts = Dictionary(bucketing: elementsToRemove)
return lazy.filter {
do {
try elementCounts.remove(countedSetElement: $0)
return false
} catch {
return true
}
}
}
}
public extension Dictionary where Value == Int {
/// Create "buckets" from a sequence of keys,
/// such as might be used for a histogram.
/// - Note: This can be used for a "counted set".
@inlinable init(bucketing unbucketedKeys: some Sequence<Key>) {
self.init(zip(unbucketedKeys, 1), uniquingKeysWith: +)
}
/// Treating this dictionary as a "counted set", reduce the element's value by 1.
/// - Throws: If `countedSetElement` is not a key.
@inlinable mutating func remove(countedSetElement: Key) throws {
guard let count = self[countedSetElement] else { throw AnyError() }
self[countedSetElement] = count == 1 ? nil : count - 1
}
}
/// `zip` a sequence with a single value, instead of another sequence.
@inlinable public func zip<Sequence: Swift.Sequence, Constant>(
_ sequence: Sequence, _ constant: Constant
) -> some Swift.Sequence<(Sequence.Element, Constant)> {
zip(sequence, **ModuleName**.sequence(constant))
}
/// An infinite sequence of a single value.
@inlinable public func sequence<Element>(_ element: Element) -> some Sequence<Element> {
let getSelf: (Element) -> Element = \.self
return sequence(first: element, next: getSelf)
}
/// A nondescript error.
public struct AnyError: Error & Equatable {
public init() { }
}