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

3

输出结果几乎正确,但我在尝试展开嵌套的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()函数,返回具有尺寸为150x200的封面图像的电影的id、标题和boxart:url)

// [
//     {"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数组,但我似乎找不到它的位置。

请点击这里进行演示


我有这个JSON数据。—— 这是JavaScript,不是JSON。 - Quentin
3个回答

4
你很接近了。我认为这是有关Observables的练习。因为你正在研究RxJS,所以重要的是不要使用索引--> [0]。在处理Observables时没有索引的概念。
理解这个问题的诀窍是仔细观察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();

注意在最后一个映射中,我们不仅映射了盒装图url,还将视频数据一并传入。这使我们获得了需要运行concatAll()的均匀嵌套数组。
我们必须调用两次concatAll()的原因是您的视频嵌套在演示中的类别中。第一次调用会展开电影,第二次调用会展开类别。 这是经过修改的jsbin,供您查看
这些都是非常好的练习。祝你好运!

1

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

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

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

0
个人而言,我会使用forEach()而不是map(),并将“正确”的boxart存储在本地变量中。请记住,map()返回一个数组。通过使用forEach,我们可以检查每个boxart并选择正确的一个。我喜欢这个解决方案,因为其他人阅读您的代码更容易理解正在发生的事情。这也允许我们在链的末尾整洁地使用concatAll()。
return movieLists.map(function(category){                      

return  category.videos.map(function(vids){
    var correctBoxSize = "No Proper Box Size Found"; 

    vids.boxarts.forEach(function(boxes){
        if (boxes.width === 150 && boxes.height === 200)
            {correctBoxSize = boxes.url}
        });

    return {
            "id": vids.id,
            "title": vids.title,
            "boxart": correctBoxSize
           };
})
}).concatAll()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接