美文网首页
RxSwift 变换操作(Transforming Observ

RxSwift 变换操作(Transforming Observ

作者: darrenW | 来源:发表于2018-09-25 21:49 被阅读33次

变换操作指的是对原始的Observable序列进行一些转换,类似于 Swift 中CollectionType的各种转换

1. buffer

buffer操作符将缓存Observable中发出的新元素,当元素达到某个数量,或者经过了特定的时间,它就会将这个元素集合发送出来。

buffer.png
🌰:
let disposeBag = DisposeBag()
let subject = PublishSubject<String>()

subject.buffer(timeSpan: 1, count: 3, scheduler: MainScheduler.instance)
        .subscribe{ print($0) }
        .disposed(by: disposeBag)
subject.onNext("A")
subject.onNext("B")
subject.onNext("C")

subject.onNext("🐯")
subject.onNext("🐭")
subject.onNext("🐱")

运行结果如下:

next(["A", "B", "C"])
next(["🐯", "🐭", "🐱"])

有一点疑问,对于bufferRxSwift的解释是

Projects each element of an observable sequence into a buffer that's sent out when either it's full or a given amount of time has elapsed, using the specified scheduler to run timers

RxSwift中,它的意思是当缓冲区满了或超过了给定的时间时,就会发出缓冲区。可是如果我们把上述代码稍微改变一下

let disposeBag = DisposeBag()
let subject = PublishSubject<String>()

subject.buffer(timeSpan: 1, count: 3, scheduler: MainScheduler.instance)
        .subscribe{ print($0) }
        .disposed(by: disposeBag)
subject.onNext("A")
subject.onNext("B")
subject.onNext("C")

//  subject.onNext("🐯")
subject.onNext("🐭")
subject.onNext("🐱")

运行结果如下:

next(["A", "B", "C"])

并没有后面的内容。因为我在很多文章里都看到说如果规定时间内不够要求的数量也会发出(有几个发几个,一个都没有发空数组 [])。所以,这点值得注意。

2. window

  • window操作符和buffer十分相似。不过buffer是周期性的将缓存的元素集合发送出来,而window周期性的将元素集合以Observable的形态发送出来。
    同时buffer要等到元素搜集完毕后,才会发出元素序列。而window可以实时发出元素序列。(这一点证明了buffer还是要元素搜集完毕后才会发出序列)
    window.png
    首先我们先这么写:
let disposeBag = DisposeBag()
let subject = PublishSubject<String>()

subject.window(timeSpan: 1, count: 3, scheduler: MainScheduler.instance)
    .subscribe{ print($0) }
    .disposed(by: disposeBag)

subject.onNext("A")
subject.onNext("B")
subject.onNext("C")

subject.onNext("🐯")
subject.onNext("🐭")
subject.onNext("🐱")

运行结果如下:

next(RxSwift.AddRef<Swift.String>)
next(RxSwift.AddRef<Swift.String>)
next(RxSwift.AddRef<Swift.String>)
next(RxSwift.AddRef<Swift.String>)
......

可见他在不断打印next(RxSwift.AddRef<Swift.String>)
如果把代码改成这样:

let disposeBag = DisposeBag()
let subject = PublishSubject<String>()

subject.window(timeSpan: 1, count: 3, scheduler: MainScheduler.instance)
    .subscribe(onNext: {
        print("subscribe:\($0)")
        $0.asObservable()
            .subscribe{ print($0) }
            .disposed(by: disposeBag)
    })
    .disposed(by: disposeBag)

subject.onNext("A")
subject.onNext("B")
subject.onNext("C")

subject.onNext("🐯")
subject.onNext("🐭")
subject.onNext("🐱")

运行结果如下:

subscribe:RxSwift.AddRef<Swift.String>
next(A)
next(B)
next(C)
completed
subscribe:RxSwift.AddRef<Swift.String>
next(🐯)
next(🐭)
next(🐱)
completed
subscribe:RxSwift.AddRef<Swift.String>
completed
subscribe:RxSwift.AddRef<Swift.String>
completed

3.map

map操作符将Observable的每个元素应用你提供的转换方法,然后返回含有转换结果的Observable

map.png
let disposeBag = DisposeBag()
Observable.of(1,2,3)
    .map{ $0 * 2 }
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

运行结果如下:

2
4
6

其实,swift中也有一个高级函数map,可以对数组中的每一个元素做一次处理

let array = [1, 2, 3]
let nums = array.map {
    return $0 * 2
}
print(nums)

结果得出:

[2, 4, 6]

4. flatMap

  • map在做转换的时候容易出现“升维”的情况。即转变之后,从一个序列变成了一个序列的序列。
  • flatMap操作符会对源Observable的每一个元素应用一个转换方法,将他们转换成Observables。 然后将这些Observables的元素合并之后再发送出来。即又将其 "拍扁"(降维)成一个Observable序列。
  • 这个操作符是非常有用的。比如当Observable的元素本生拥有其他的Observable时,我们可以将所有子Observables的元素发送出来。
flatMap.png
let disposeBag = DisposeBag()
let first = BehaviorSubject.init(value: "A")
let second = BehaviorSubject.init(value: "B")
let variable = Variable.init(first)

variable.asObservable()
    .flatMap{ $0 }
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)
first.onNext("1")
variable.value = second
second.onNext("2")
first.onNext("3")

打印结果如下:

A
1
B
2
3

我们依然可以在Swift中找到高级函数flatMap,它相比map有两点不同

  • flatMap返回后的数组中不存在nil,同时它会把Optional解包
  • flatMap还能把数组中存有数组的数组(二维数组、N维数组)一同打开变成一个新的数组
  • 也能把两个不同的数组合并成一个数组,这个合并的数组元素个数是前面两个数组元素个数的乘积

只举一个🌰:

let array = [[1, 2, 3], [4, 5, 6]]
let nums = array.flatMap{ $0 }
print(nums)

运行结果如下:

[1, 2, 3, 4, 5, 6]

5. flatMapLatest

flatMapLatestflatMap的唯一区别是:flatMapLatest只会接收最新的value事件

flatMapLatest.png
将上述代码中flatMap改为flatMapLatest
let disposeBag = DisposeBag()
let first = BehaviorSubject.init(value: "A")
let second = BehaviorSubject.init(value: "B")
let variable = Variable.init(first)

variable.asObservable()
    .flatMapLatest{ $0 }
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)
first.onNext("1")
variable.value = second
second.onNext("2")
first.onNext("3")

运行结果如下:

A
1
B
2

6. concatMap

concatMap操作符将源Observable的每一个元素应用一个转换方法,将他们转换成Observables。然后让这些Observables 按顺序的发出元素,当前一个Observable元素发送完毕后,后一个Observable才可以开始发出元素。等待前一个Observable产生完成事件后,才对后一个Observable进行订阅

concatMap.png
let disposeBag = DisposeBag()
let first = BehaviorSubject.init(value: "A")
let second = BehaviorSubject.init(value: "B")
let variable = Variable.init(first)

variable.asObservable()
    .concatMap{ $0 }
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)
first.onNext("1")
first.onNext("2")

variable.value = second
second.onNext("3")
second.onNext("4")

first.onCompleted()
second.onNext("5")

运行结果如下:

A
1
2
4
5

7. scan

scan操作符将对第一个元素应用一个函数,将结果作为第一个元素发出。然后,将结果作为参数填入到第二个元素的应用函数中,创建第二个元素。以此类推,直到遍历完全部的元素。

scan.png
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 4, 5)
    .scan(0) { acum, elem  in
        acum + elem
    }
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

运行结果如下:

1
3
6
10
15

8. groupBy

  • groupBy操作符将源Observable分解为多个子Observable,然后将这些子Observable发送出来。
  • 也就是说该操作符会将元素通过某个键进行分组,然后将分组后的元素序列以Observable的形态发送出来。
    groupBy.png
let disposeBag = DisposeBag()
Observable<Int>.of(0, 1, 2, 3, 4, 5)
    .groupBy { (element) -> String in
        return element % 2 == 0 ? "偶数" : "奇数"
}
    .subscribe { (event) in
        switch event {
        case .next(let group):
            group.asObservable().subscribe({ (event) in
                print("key:\(group.key)  event:\(event)")
            })
            .disposed(by: disposeBag)
        default:
            print("")
        }
}.disposed(by: disposeBag)

运行结果如下:

key:偶数  event:next(0)
key:奇数  event:next(1)
key:偶数  event:next(2)
key:奇数  event:next(3)
key:偶数  event:next(4)
key:奇数  event:next(5)
key:奇数  event:completed
key:偶数  event:completed

相关文章

网友评论

      本文标题:RxSwift 变换操作(Transforming Observ

      本文链接:https://www.haomeiwen.com/subject/wudxoftx.html