【问题标题】:refactor fat arrow nested rxjs stream重构胖箭头嵌套的 rxjs 流
【发布时间】:2017-01-12 09:08:55
【问题描述】:

我在玩http://reactivex.io/learnrx/。为了更好地学习 rxjs。

我正在处理的数组如下。我只是想把 id 从数组中取出。

我能够得到工作的答案,但觉得答案可以写得更好。

var movieLists = [
        {
            name: "New Releases",
            videos: [
                {
                    "id": 70111470,
                    "title": "Die Hard",
                    "boxart": "http://cdn-0.nflximg.com/images/2891/DieHard.jpg",
                    "uri": "http://api.netflix.com/catalog/titles/movies/70111470",
                    "rating": 4.0,
                    "bookmark": []
                },
                {
                    "id": 654356453,
                    "title": "Bad Boys",
                    "boxart": "http://cdn-0.nflximg.com/images/2891/BadBoys.jpg",
                    "uri": "http://api.netflix.com/catalog/titles/movies/70111470",
                    "rating": 5.0,
                    "bookmark": [{ id: 432534, time: 65876586 }]
                }
            ]
        },
        {
            name: "Dramas",
            videos: [
                {
                    "id": 65432445,
                    "title": "The Chamber",
                    "boxart": "http://cdn-0.nflximg.com/images/2891/TheChamber.jpg",
                    "uri": "http://api.netflix.com/catalog/titles/movies/70111470",
                    "rating": 4.0,
                    "bookmark": []
                },
                {
                    "id": 675465,
                    "title": "Fracture",
                    "boxart": "http://cdn-0.nflximg.com/images/2891/Fracture.jpg",
                    "uri": "http://api.netflix.com/catalog/titles/movies/70111470",
                    "rating": 5.0,
                    "bookmark": [{ id: 432534, time: 65876586 }]
                }
            ]
        }
    ];

这是我想出的答案

          movieLists
                  .map( movieList => movieList.videos
                  .map(video => video.id)  )   // don't like this part
                  .concatAll()

我基本上是在另一个地图中嵌套一个地图,然后调用 concat all。

是否可以重构第二个地图粗箭头,使其可以位于第一个之外?

.map()
.map()

【问题讨论】:

    标签: ecmascript-6 rxjs reactive-programming


    【解决方案1】:

    只需更改运算符的顺序即可。

    Observable.from(movieLists)
      .map(movie => movie.videos)
      .concatAll()
      .map(movie => movie.id);
    

    【讨论】:

    • 我什至没有想到这一点。我还发现使用 flatmap 很有效,但这更好,谢谢。
    【解决方案2】:

    您可以在映射到电影后使用concatAll()

    var movieLists = [
        {
            name: "New Releases",
            videos: [
                {
                    "id": 70111470,
                    "title": "Die Hard",
                    "boxart": "http://cdn-0.nflximg.com/images/2891/DieHard.jpg",
                    "uri": "http://api.netflix.com/catalog/titles/movies/70111470",
                    "rating": 4.0,
                    "bookmark": []
                },
                {
                    "id": 654356453,
                    "title": "Bad Boys",
                    "boxart": "http://cdn-0.nflximg.com/images/2891/BadBoys.jpg",
                    "uri": "http://api.netflix.com/catalog/titles/movies/70111470",
                    "rating": 5.0,
                    "bookmark": [{ id: 432534, time: 65876586 }]
                }
            ]
        },
        {
            name: "Dramas",
            videos: [
                {
                    "id": 65432445,
                    "title": "The Chamber",
                    "boxart": "http://cdn-0.nflximg.com/images/2891/TheChamber.jpg",
                    "uri": "http://api.netflix.com/catalog/titles/movies/70111470",
                    "rating": 4.0,
                    "bookmark": []
                },
                {
                    "id": 675465,
                    "title": "Fracture",
                    "boxart": "http://cdn-0.nflximg.com/images/2891/Fracture.jpg",
                    "uri": "http://api.netflix.com/catalog/titles/movies/70111470",
                    "rating": 5.0,
                    "bookmark": [{ id: 432534, time: 65876586 }]
                }
            ]
        }
    ];
    
    Rx.Observable.from(movieLists)
        .map(movieList => movieList.videos)
        .concatAll()
        .map(video => video.id)
        .do(console.log)
        .subscribe();
    <script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>

    但是: 基本上你想要展平 Array 并提取 id - 这里根本不需要 RxJS,使用原生方法也应该更快:

    var movieLists = [
        {
            name: "New Releases",
            videos: [
                {
                    "id": 70111470,
                    "title": "Die Hard",
                    "boxart": "http://cdn-0.nflximg.com/images/2891/DieHard.jpg",
                    "uri": "http://api.netflix.com/catalog/titles/movies/70111470",
                    "rating": 4.0,
                    "bookmark": []
                },
                {
                    "id": 654356453,
                    "title": "Bad Boys",
                    "boxart": "http://cdn-0.nflximg.com/images/2891/BadBoys.jpg",
                    "uri": "http://api.netflix.com/catalog/titles/movies/70111470",
                    "rating": 5.0,
                    "bookmark": [{ id: 432534, time: 65876586 }]
                }
            ]
        },
        {
            name: "Dramas",
            videos: [
                {
                    "id": 65432445,
                    "title": "The Chamber",
                    "boxart": "http://cdn-0.nflximg.com/images/2891/TheChamber.jpg",
                    "uri": "http://api.netflix.com/catalog/titles/movies/70111470",
                    "rating": 4.0,
                    "bookmark": []
                },
                {
                    "id": 675465,
                    "title": "Fracture",
                    "boxart": "http://cdn-0.nflximg.com/images/2891/Fracture.jpg",
                    "uri": "http://api.netflix.com/catalog/titles/movies/70111470",
                    "rating": 5.0,
                    "bookmark": [{ id: 432534, time: 65876586 }]
                }
            ]
        }
    ];
    
    // Step 1: get all the videos as an multi-dimensional array
    const videos = movieLists.map(movie => movie.videos);
    // Step 2: flatten the array
    const flatVideos = [].concat.apply([], videos);
    // Step 3: Map to ids
    const videoIds = flatVideos.map(video => video.id);
    console.log(videoIds);

    我已经分 3 步编写了这个,但也可以将它们连接起来。

    【讨论】:

    • 我想出了如何使用平面地图 console.log(movieLists .map(movieList => movieList.videos) .flatMap(videos => videos) .map(post => post.id ) ).
    • 我同意 rxjs 没有用,但我的目标是适应它。
    • 好的,太好了 - 也许您想发布您的解决方案并接受它作为答案,因为其他人看到不同的解决方案可能会很有趣
    【解决方案3】:

    您可以在单个运算符中完成:

    Observable.from(movieLists)
      .concatMap(
        movie => movie.videos, 
        (_, video) => video.id
      )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-26
      • 1970-01-01
      • 2017-03-03
      • 2016-02-08
      • 2023-03-12
      相关资源
      最近更新 更多