Skip to content

Instantly share code, notes, and snippets.

@dduan
Created July 30, 2019 19:00
Show Gist options
  • Save dduan/40bdb57b9324b197251dc5ce29230c41 to your computer and use it in GitHub Desktop.
Save dduan/40bdb57b9324b197251dc5ce29230c41 to your computer and use it in GitHub Desktop.
Combine framework: remove duplicates by key paths.
import Combine
@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
extension Publisher {
func removeDuplicates<Property>(by keyPath: KeyPath<Output, Property>)
-> Publishers.RemoveDuplicates<Self> where Property: Equatable
{
return self.removeDuplicates {
$0[keyPath: keyPath] == $1[keyPath: keyPath]
}
}
func removeDuplicates<Property0, Property1>(
by keyPath0: KeyPath<Output, Property0>,
_ keyPath1: KeyPath<Output, Property1>
) -> Publishers.RemoveDuplicates<Self> where
Property0: Equatable, Property1: Equatable
{
return self.removeDuplicates {
$0[keyPath: keyPath0] == $1[keyPath: keyPath0] &&
$0[keyPath: keyPath1] == $1[keyPath: keyPath1]
}
}
func removeDuplicates<Property0, Property1, Property2>(
by keyPath0: KeyPath<Output, Property0>,
_ keyPath1: KeyPath<Output, Property1>,
_ keyPath2: KeyPath<Output, Property2>
) -> Publishers.RemoveDuplicates<Self> where
Property0: Equatable, Property1: Equatable, Property2: Equatable
{
return self.removeDuplicates {
$0[keyPath: keyPath0] == $1[keyPath: keyPath0] &&
$0[keyPath: keyPath1] == $1[keyPath: keyPath1] &&
$0[keyPath: keyPath2] == $1[keyPath: keyPath2]
}
}
func removeDuplicates<Property0, Property1, Property2, Property3>(
by keyPath0: KeyPath<Output, Property0>,
_ keyPath1: KeyPath<Output, Property1>,
_ keyPath2: KeyPath<Output, Property2>,
_ keyPath3: KeyPath<Output, Property3>
) -> Publishers.RemoveDuplicates<Self> where
Property0: Equatable, Property1: Equatable, Property2: Equatable, Property3: Equatable
{
return self.removeDuplicates {
$0[keyPath: keyPath0] == $1[keyPath: keyPath0] &&
$0[keyPath: keyPath1] == $1[keyPath: keyPath1] &&
$0[keyPath: keyPath2] == $1[keyPath: keyPath2] &&
$0[keyPath: keyPath3] == $1[keyPath: keyPath3]
}
}
}
// etc, maybe repeat for more properties.
// until Swift have variadic generic parameters
@jimmya
Copy link

jimmya commented Jan 3, 2024

@dduan using variadic generic parameters available in Swift 5.9:

extension Publisher {
    func removeDuplicates<each K: Equatable>(
        by keyPaths: repeat (KeyPath<Output, each K>)
    ) -> Publishers.RemoveDuplicates<Self> {
        removeDuplicates { lhs, rhs in
            func equate<Key: Equatable>(_ keyPath: (KeyPath<Output, Key>)) -> Bool {
                lhs[keyPath: keyPath] == rhs[keyPath: keyPath]
            }

            var allSatisfy = true
            repeat equate(each keyPaths) ? () : (allSatisfy = false)
            return allSatisfy
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment