使用map(),filter()和concatAll()函数提取Javascript数据

时间:2015-07-31 12:55:34

标签: javascript functional-programming

输出几乎是正确的,但我无法展平嵌套的boxart数组。

Javascript数据:

var movieLists = {
    name: "Instant Queue",
    videos : [
        {    
             "id": 70111470,
             "title": "Die Hard",
             "boxarts": [
                 {width: 150, height:200, url:"http://cdn-0.nflximg.com/images/2891/DieHard150.jpg"}, 
                 {width: 200, height:200, url:"http://cdn-0.nflximg.com/images/2891/DieHard200.jpg"}
             ],
            "url": "http://api.netflix.com/catalog/titles/movies/70111470",
            "rating": 4.0,
            "bookmark": [{ id:432534, time:65876586 }]
        },
        {
            "id": 654356453,
            "title": ....,
        }];

预期输出(仅使用功能.map().filter().concatAll(),返回ID,标题,boxart:包含boxart的电影的网址图片尺寸150x200

// [
//     {"id": 675465,"title": "Fracture","boxart":"http://cdn-0...." },
//     {"id": 65432445,"title": "The Chamber","boxart":"http://cdn-0...." },
//     {"id": 654356453,...}
// ];

当前输出:

// [                                    //boxart value is an array
//     {"id": 675465,"title": "Fracture","boxart":["http://cdn-0...."]},
//     {"id": 65432445,"title": "The Chamber","boxart":["http://cdn-0...."]},
//     {"id": 654356453,...}
// ];

我的解决方案

return movieLists.map(function (category) {
   return category.videos.map(function (video) {
       return {
           id: video.id,
           title: video.title,
           boxart: video.boxarts.filter(function (boxartFeature) {
               return boxartFeature.width === 150 && boxartFeature.height === 200;
           })
               .map(function (boxartProp) {
               return boxartProp.url;
           })
       };
   });
 }).concatAll(); //Flattens nested array by 1 dimension (please see demo)

我知道我需要应用.concatAll()函数来删除嵌套的boxart数组,但我似乎无法找到所在的位置。

请点击here for demo

3 个答案:

答案 0 :(得分:3)

你非常接近。我认为这是Observables的练习。因为您正在研究RxJS,所以 NOT 使用索引非常重要 - > [0]。处理Observable时没有索引的概念。

理解这个问题的诀窍是仔细研究concatAll()正在做什么。它需要一个二维数组并返回一个扁平数组。

[[1,2],[3,4]] --> [1,2,3,4]

使用当前代码,您将boxartProp.url映射到嵌套数组,但其余属性不是。你或多或少现在拥有的是:[1,2,3,[4]]。你想要的是一个均匀嵌套的数组:[[1],[2],[3],[4]]。重要的原因是因为concatAll()期望每个成员都是一个子阵列。如果您还没有看过,我建议您通过Jafar Husain观看this video。他很棒,并且在视频中从头开始实现concatAll

只需进行一些小的调整即可实现您的目标。

return movieLists.map(function(category) {
    return category.videos.map(function(video) {
        return video.boxarts.filter(function(boxart) {
            return boxart.width === 150;
        }).map(function(boxart) {
            return {id: video.id, title: video.title, boxart: boxart.url};
        });
    }).concatAll();
}).concatAll();

请注意,在最后一张地图中,我们如何传输视频数据,而不仅仅是映射boxart网址。这为我们提供了运行concatAll()所需的均匀嵌套数组。

我们必须两次致电concatAll()的原因是您的视频嵌套在演示中的类别中。第一个电话会使电影变得平淡,第二个电话会使这些类别变得扁平化。

Here is the modified jsbin for your review

这些是一些很好的练习。祝你好运!

答案 1 :(得分:1)

map返回一个数组。您将map的结果存储在boxart属性中。

如果您不想在boxart中存储数组,只需存储数组的第一个成员(索引0):

//...
.map(function (boxartProp) {
     return boxartProp.url;
})[0]

答案 2 :(得分:0)

就个人而言,我会使用forEach()而不是map()并存储"正确的"局部变量中的boxart。请记住map()返回一个数组。通过使用forEach,我们可以检查每个boxart并选择正确的boxart。我喜欢这个解决方案,因为阅读代码的其他人更容易理解发生了什么。这也允许我们在链的末尾巧妙地使用concatAll()。

sprintf