可观察的distinctUntilChanged返回重复项

时间:2018-08-01 12:26:50

标签: ios swift rx-swift

设置:RxSwift 4.2 Swift 4.1 Xcode 9.4.1

我目前正在使用distinctUntilChanged来获取唯一值。 但就我而言,它仅适用于“排序”值。

例如此处:

func unique(source: Observable<Int>) -> Observable<Int> {
    return source.distinctUntilChanged()
}

这是对应的测试:

func testUnique() {
    let input = Observable.from([1,2,3,4,4,5,4])
    let expectation = [Recorded.next(0, 1),
                       Recorded.next(0, 2),
                       Recorded.next(0, 3),
                       Recorded.next(0, 4),
                       Recorded.next(0, 5),
                       Recorded.completed(0)]

    _ = Class().unique(source: input).subscribe(observer)

    XCTAssertEqual(observer.events, expectation)
}

我的测试失败:

XCTAssertEqual failed: ("[next(1) @ 0, next(2) @ 0, next(3) @ 0, next(4) @ 0, next(5) @ 0, next(4) @ 0, completed @ 0]")
is not equal to ("[next(1) @ 0, next(2) @ 0, next(3) @ 0, next(4) @ 0, next(5) @ 0, completed @ 0]") - 

所以最后一个4是重复的。
这是预期的行为还是错误?

3 个答案:

答案 0 :(得分:1)

这是预期的行为。 distinctUntilChanged正在与流中的先前值进行比较,在您的情况下,它应发出:

c_array = (c_types.c_int * M * N)(*[(c_types.c_int * M)(*lst) for lst in py_list])

认为您可以使用let expectation = [Recorded.next(0, 1), Recorded.next(0, 2), Recorded.next(0, 3), Recorded.next(0, 4), Recorded.next(0, 5), Recorded.next(0, 4), Recorded.completed(0)] 来记住以前的值,然后只需检查它是否需要发出新的值即可。这是使用scan的快速解决方案:

scan

答案 1 :(得分:0)

这确实是预期的行为,因此将运算符称为“ .distinct UntilChanged ()”。您显然想要的是'.distinct()',但它在基本的'RxSwift'框架中不可用,仅在'RxSwiftExt'框架-https://github.com/RxSwiftCommunity/RxSwiftExt#distinct

中不可用

答案 2 :(得分:0)

我自己做了一个简单的类型指定答案。
基本上是RxSwiftExt distinct解决方案:

func unique(source: Observable<Int>) -> Observable<Int> {
    var cache = Set<Int>()

    return source.flatMap { element -> Observable<Int> in
        if cache.contains(element) {
            return Observable<Int>.empty()
        } else {
            cache.insert(element)
            return Observable<Int>.just(element)
        }
    }
}