Skip to content

Commit e4be13c

Browse files
committed
Added CurrentValuePublisher.removeDuplicates(…)
1 parent 50c1938 commit e4be13c

2 files changed

Lines changed: 117 additions & 74 deletions

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import Combine
2+
3+
extension CurrentValuePublisher {
4+
5+
/// Returns a new `CurrentValuePublisher` that emits values only when they differ from the
6+
/// previous value, as determined by the provided predicate.
7+
///
8+
/// - Parameter predicate: A closure that compares the previous and current values and returns
9+
/// `true` if they are considered duplicates.
10+
/// - Returns: A `CurrentValuePublisher` that emits only distinct values.
11+
public func removeDuplicates(
12+
by predicate: @escaping (Output, Output) -> Bool
13+
) -> CurrentValuePublisher<Output, Failure> {
14+
switch self.storage {
15+
case .constant:
16+
return self
17+
case .subject:
18+
let initialValue = self.value
19+
20+
let upstream = self.dropFirst()
21+
.drop { predicate(initialValue, $0) }
22+
.removeDuplicates(by: predicate)
23+
24+
return CurrentValuePublisher(
25+
initial: initialValue,
26+
upstream: upstream
27+
)
28+
}
29+
}
30+
31+
}
32+
33+
extension CurrentValuePublisher where Output: Equatable {
34+
35+
/// Returns a new `CurrentValuePublisher` that emits values only when they differ from the
36+
/// previous value.
37+
///
38+
/// - Returns: A `CurrentValuePublisher` that emits only distinct values.
39+
public func removeDuplicates() -> CurrentValuePublisher<Output, Failure> {
40+
return self.removeDuplicates(by: ==)
41+
}
42+
43+
}

Tests/CombineExtensionsTests/CurrentValuePublisher/CurrentValuePublisherTests.swift

Lines changed: 74 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -605,80 +605,80 @@ class CurrentValuePublisherTests: XCTestCase {
605605
XCTAssertEqual(values, ["10", "11", "20", "12", "30", "30", "12"])
606606
}
607607

608-
// // ============================================================================ //
609-
// // MARK: - Remove Duplicates Operator
610-
// // ============================================================================ //
611-
//
612-
// func testRemoveDuplicates_constant() {
613-
// var cancellables = Set<AnyCancellable>()
614-
// var values = [Int]()
615-
//
616-
// CurrentValuePublisher(value: 1)
617-
// .removeDuplicates()
618-
// .sink { values.append($0) }
619-
// .store(in: &cancellables)
620-
//
621-
// XCTAssertEqual(values, [1])
622-
// }
623-
//
624-
// func testRemoveDuplicates_subject() {
625-
// var cancellables = Set<AnyCancellable>()
626-
// var values = [Int]()
627-
//
628-
// let subject = CurrentValueSubject<Int, Never>(1)
629-
//
630-
// CurrentValuePublisher(subject)
631-
// .removeDuplicates()
632-
// .sink { values.append($0) }
633-
// .store(in: &cancellables)
634-
//
635-
// XCTAssertEqual(values, [1])
636-
//
637-
// subject.send(1)
638-
// XCTAssertEqual(values, [1])
639-
//
640-
// subject.send(1)
641-
// XCTAssertEqual(values, [1])
642-
//
643-
// subject.send(2)
644-
// XCTAssertEqual(values, [1, 2])
645-
//
646-
// subject.send(2)
647-
// XCTAssertEqual(values, [1, 2])
648-
//
649-
// subject.send(3)
650-
// XCTAssertEqual(values, [1, 2, 3])
651-
// }
652-
//
653-
// func testRemoveDuplicate_subject_customPredicate() {
654-
// var cancellables = Set<AnyCancellable>()
655-
// var values = [Int]()
656-
//
657-
// let subject = CurrentValueSubject<Int, Never>(1)
658-
//
659-
// CurrentValuePublisher(subject)
660-
// .removeDuplicates(by: { old, new in new < old })
661-
// .sink { values.append($0) }
662-
// .store(in: &cancellables)
663-
//
664-
// XCTAssertEqual(values, [1])
665-
//
666-
// subject.send(4)
667-
// XCTAssertEqual(values, [1, 4])
668-
//
669-
// subject.send(3)
670-
// XCTAssertEqual(values, [1, 4])
671-
//
672-
// subject.send(6)
673-
// XCTAssertEqual(values, [1, 4, 6])
674-
//
675-
// subject.send(2)
676-
// XCTAssertEqual(values, [1, 4, 6])
677-
//
678-
// subject.send(7)
679-
// XCTAssertEqual(values, [1, 4, 6, 7])
680-
// }
681-
//
608+
// ============================================================================ //
609+
// MARK: - Remove Duplicates Operator
610+
// ============================================================================ //
611+
612+
func testRemoveDuplicates_constant() {
613+
var cancellables = Set<AnyCancellable>()
614+
var values = [Int]()
615+
616+
CurrentValuePublisher(value: 1)
617+
.removeDuplicates()
618+
.sink { values.append($0) }
619+
.store(in: &cancellables)
620+
621+
XCTAssertEqual(values, [1])
622+
}
623+
624+
func testRemoveDuplicates_subject() {
625+
var cancellables = Set<AnyCancellable>()
626+
var values = [Int]()
627+
628+
let subject = CurrentValueSubject<Int, Never>(1)
629+
630+
CurrentValuePublisher(subject)
631+
.removeDuplicates()
632+
.sink { values.append($0) }
633+
.store(in: &cancellables)
634+
635+
XCTAssertEqual(values, [1])
636+
637+
subject.send(1)
638+
XCTAssertEqual(values, [1])
639+
640+
subject.send(1)
641+
XCTAssertEqual(values, [1])
642+
643+
subject.send(2)
644+
XCTAssertEqual(values, [1, 2])
645+
646+
subject.send(2)
647+
XCTAssertEqual(values, [1, 2])
648+
649+
subject.send(3)
650+
XCTAssertEqual(values, [1, 2, 3])
651+
}
652+
653+
func testRemoveDuplicate_subject_customPredicate() {
654+
var cancellables = Set<AnyCancellable>()
655+
var values = [Int]()
656+
657+
let subject = CurrentValueSubject<Int, Never>(1)
658+
659+
CurrentValuePublisher(subject)
660+
.removeDuplicates(by: { old, new in new < old })
661+
.sink { values.append($0) }
662+
.store(in: &cancellables)
663+
664+
XCTAssertEqual(values, [1])
665+
666+
subject.send(4)
667+
XCTAssertEqual(values, [1, 4])
668+
669+
subject.send(3)
670+
XCTAssertEqual(values, [1, 4])
671+
672+
subject.send(6)
673+
XCTAssertEqual(values, [1, 4, 6])
674+
675+
subject.send(2)
676+
XCTAssertEqual(values, [1, 4, 6])
677+
678+
subject.send(7)
679+
XCTAssertEqual(values, [1, 4, 6, 7])
680+
}
681+
682682
// // ============================================================================ //
683683
// // MARK: - CombineLatest Operator
684684
// // ============================================================================ //

0 commit comments

Comments
 (0)