Combining Operatorsチートシート

#Combining Operators

RxSwiftでコードを書く必要があり、学習中です。
参考文献を元に学んだ内容をすぐ振り返れるようにまとめていきます。
今回はCombining Operatorsについてまとめました。
完全に自分の解釈でコメントを載せていますが、解釈に誤りがありましたら、コメント欄より教えてください。



##startWith()
```Swift
example(of: "startWith") {
  // 1
  let numbers = Observable.of(2, 3, 4)
  
  // 2
  let observable = numbers.startWith(1)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}
```
###コンパイル結果
![Screen Shot 2020-11-30 at 10.42.56 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535198/81f6e8a9-fe98-685a-9637-d613a4134301.png)


##Observable.concat
####同じ型同士の時のみ、Concatできる！
```Swift
example(of: "Observable.concat") {
  // 1
  let first = Observable.of(1, 2, 3)
  let second = Observable.of(4, 5, 6)
  
  // 2
  let observable = Observable.concat([first, second])
  
  observable.subscribe(onNext: { value in
    print(value)
  })
}
```
###コンパイル結果
![Screen Shot 2020-11-30 at 10.42.47 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535198/a38337df-7ad6-91cf-586d-3b75842fe7ec.png)

##concat
```Swift
example(of: "concat") {
  let germanCities = Observable.of("Berlin", "Münich", "Frankfurt")
  let spanishCities = Observable.of("Madrid", "Barcelona", "Valencia")
  
  let observable = germanCities.concat(spanishCities)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}

```
###コンパイル結果
![Screen Shot 2020-11-30 at 10.42.05 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535198/ecd84408-5a8e-db2b-0287-1233f7113114.png)


##concatMaｐ
```Swift
example(of: "concatMap") {
  // 1
  let sequences = [
    "German cities": Observable.of("Berlin", "Münich", "Frankfurt"),
    "Spanish cities": Observable.of("Madrid", "Barcelona", "Valencia")
  ]

  // 2
  let observable = Observable.of("German cities", "Spanish cities")
    .concatMap { country in sequences[country] ?? .empty() }

  // 3
  _ = observable.subscribe(onNext: { string in
      print(string)
    })
}

```
###コンパイル結果
![Screen Shot 2020-11-30 at 10.41.49 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535198/d505543f-63af-ae4e-5bab-833bf00fc179.png)


##mege
####maxConcurrentを使うことで、同時にObserveするSequenceの上限を設定できる。
```Swift
example(of: "merge") {
  // 1
  let left = PublishSubject<String>()
  let right = PublishSubject<String>()
    
    // 2
    let source = Observable.of(left.asObservable(), right.asObservable())
    
    // 3
    let observable = source.merge(maxConcurrent: 2)
    _ = observable.subscribe(onNext: { value in
      print(value)
    })

    // 4
    var leftValues = ["Berlin", "Munich", "Frankfurt"]
    var rightValues = ["Madrid", "Barcelona", "Valencia"]
    
    repeat {
        switch Bool.random() {
        case true where !leftValues.isEmpty:
            left.onNext("Left:  " + leftValues.removeFirst())
        case false where !rightValues.isEmpty:
            right.onNext("Right: " + rightValues.removeFirst())
        default:
            break
        }
    } while !leftValues.isEmpty || !rightValues.isEmpty

    // 5
    left.onCompleted()
    right.onCompleted()
  }

```
###コンパイル結果
![Screen Shot 2020-11-30 at 10.41.22 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535198/51a7931e-729e-3664-5f01-67613c29254e.png)


##combineLatest
####全てのObservableから値が発信されるまで、何もしない。異なる方のSequenceをまとめて、最新の値を取り出す。
```Swift
example(of: "combineLatest") {
  let left = PublishSubject<String>()
  let right = PublishSubject<String>()

    // 1
//    let observable = Observable.combineLatest(left, right) {
//      lastLeft, lastRight in
//      "\(lastLeft) \(lastRight)"
//    }
    
// 1   combineLatestでタプルにして、filterをかける方法がよく使われる。
//    let observable = Observable
//      .combineLatest(left, right) { ($0, $1) }
//      .filter { !$0.0.isEmpty }

    
    // 1: Stringが確か受付内ため、余り使われない方法
    let observable = Observable.combineLatest([left, right]) {
      strings in strings.joined(separator: " ")
    }


    _ = observable.subscribe(onNext: { value in
      print(value)
    })

    // 2
    print("> Sending a value to Left")
    left.onNext("Hello,")
    print("> Sending a value to Right")
    right.onNext("world")
    print("> Sending another value to Right")
    right.onNext("Swift")
    print("> Sending another value to Left")
    left.onNext("Have a good day,")

    left.onCompleted()
    right.onCompleted()
  }


```
###コンパイル結果
![Screen Shot 2020-11-30 at 10.41.09 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535198/fe2f4375-1cf1-5070-0497-26fdbf6ca77f.png)


##combine user choice and value

####ユーザーの設定が変更した時に、表示値を変える
```Swift
example(of: "combine user choice and value") {
  let choice: Observable<DateFormatter.Style> = Observable.of(.short, .long)
  let dates = Observable.of(Date())
  
  let observable = Observable.combineLatest(choice, dates) {
    format, when -> String in
    let formatter = DateFormatter()
    formatter.dateStyle = format
    return formatter.string(from: when)
  }
  
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}

```
###コンパイル結果
![Screen Shot 2020-11-30 at 10.40.52 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535198/2f3fbf25-0f55-393e-4529-201f5c1fb8eb.png)


##zip

####indexed sequencing: ペアが成立しなくなったら、zipは値を発しなくなるが、observableがCompleteするまで処理が終わらないため、observableが完了していることを確認すること。
```Swift
example(of: "zip") {
  enum Weather {
    case cloudy
    case sunny
  }
    
    let left: Observable<Weather> = Observable.of(.sunny, .cloudy, .cloudy, .sunny, .cloudy)
  let right = Observable.of("Lisbon", "Copenhagen", "London", "Madrid", "Vienna")

    let observable = Observable.zip(left, right) { weather, city in
      return "It's \(weather) in \(city)"
    }
    _ = observable.subscribe(onNext: { value in
      print(value)
    })
    
  }

```
###コンパイル結果
![Screen Shot 2020-11-30 at 10.40.38 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535198/ff4cc263-c9e2-dec4-dc18-2fdf6b27b237.png)


##withLatestFrom
```Swift
example(of: "withLatestFrom") {
  // 1
  let button = PublishSubject<Void>()
  let textField = PublishSubject<String>()
  
  // 2
//the trigger observableが撮りガー
   let  observable  =  textField.sample(button)
//data Observableがトリガー
//  let observable = button.withLatestFrom(textField)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })

  // 3
    
  textField.onNext("Par")
  textField.onNext("Pari")
  textField.onNext("Paris")
  button.onNext(())
  button.onNext(())
}

```
###コンパイル結果
![Screen Shot 2020-11-30 at 10.40.24 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535198/5ae33108-641f-a851-fba3-b75c4daa26d6.png)


##amb
####二つのObservableのどちらをつかうかAmbiguousな場合。 使い所：connecting to redundant servers and sticking with the one that responds first.
```Swift
example(of: "amb") {
  let left = PublishSubject<String>()
  let right = PublishSubject<String>()
  
  // 1
  let observable = left.amb(right)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
  
  // 2
  left.onNext("Lisbon")
  right.onNext("Copenhagen")
  left.onNext("London")
  left.onNext("Madrid")
  right.onNext("Vienna")
  
  left.onCompleted()
  right.onCompleted()
}

```
###コンパイル結果
![Screen Shot 2020-11-30 at 10.40.08 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535198/438ef1b0-13d6-0cf4-356b-e818157e5475.png)


##switchLatest
```Swift
example(of: "switchLatest") {
  // 1
  let one = PublishSubject<String>()
  let two = PublishSubject<String>()
  let three = PublishSubject<String>()
  
  let source = PublishSubject<Observable<String>>()

    // 2
    let observable = source.switchLatest()
    let disposable = observable.subscribe(onNext: { value in
      print(value)
    })

    // 3
    source.onNext(one)
    one.onNext("Some text from sequence one")
    two.onNext("Some text from sequence two")
    
    source.onNext(two)
    two.onNext("More text from sequence two")
    one.onNext("and also from sequence one")
    
    source.onNext(three)
    two.onNext("Why don't you see me?")
    one.onNext("I'm alone, help me")
    three.onNext("Hey it's three. I win.")
    
    source.onNext(one)
    one.onNext("Nope. It's me, one!")
    disposable.dispose()
  }

```
###コンパイル結果
![Screen Shot 2020-11-30 at 10.39.53 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535198/f2c13569-7b13-852c-172b-45bdd847d182.png)


##reduce
####注意:sequencesが完了しないと、Summaryがemitされない。
```Swift
example(of: "reduce") {
  let source = Observable.of(1, 3, 5, 7, 9)
  
  // 1
//  let observable = source.reduce(0, accumulator: +)
    let observable = source.reduce(0){summary, newValue in
        return summary + newValue
    }

  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}

```
###コンパイル結果
![Screen Shot 2020-11-30 at 10.39.33 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535198/8b24f7d0-5f07-1811-1c12-83330fef1e23.png)


##scan

####累計、統計、状態をコンピュートする際に使える。
####値が変わると毎回、Observableから値がEmitされる。
```Swift
example(of: "scan") {
  let source = Observable.of(1, 3, 5, 7, 9)
  
  let observable = source.scan(0, accumulator: +)
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}
```
###コンパイル結果
![Screen Shot 2020-11-30 at 10.38.40 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535198/b743c3f5-af72-aa94-019b-26fd3451d5d2.png)


##練習
```Swift
example(of: "Challeng1") {
  let source = Observable.of(1, 3, 5, 7, 9)
  
    let scanedObservable = source.scan(0, accumulator: +)
    let observable =  Observable.zip(source, scanedObservable){current, total -> String in
        return "Total:\(String(total)), Current:\(String(current)))"
    }
    
  _ = observable.subscribe(onNext: { value in
    print(value)
  })
}
```
###コンパイル結果
![Screen Shot 2020-11-30 at 10.38.28 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535198/f782a770-3751-1324-d5d5-068ad5f3e358.png)


##練習
####acc(current, accumuratedValue)となるから、acc.1 + currentとしている。
```Swift
//acc(current, accumuratedValue)となるから、acc.1 + currentとしている。
example(of: "Challeng2") {
  let source = Observable.of(1, 3, 5, 7, 9)
  
    let  observable = source.scan((0, 0)) { acc, current in
        print("acc\(acc)")
        print("current\(current)")
        return (current, acc.1 + current)
    }
    
    _ = observable.subscribe(onNext: { tuple in
        print("Value = \(tuple.0)   Running total = \(tuple.1)")
    })
    
}

```
###コンパイル結果
![Screen Shot 2020-11-30 at 10.38.17 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535198/ab97bf46-4288-b28d-1547-436897b50d6b.png)

###参考文献
1.Combining Operators Written by Florent Pillet
Chapter9 Transforming Operators Written by Scott Gardner
詳細が気になる方はこちらをご参照ください！
https://www.raywenderlich.com/13285844-rxswift-reactive-programming-with-swift-update-now-available