使用Flatmap地图和过滤器代替循环

时间:2018-04-17 10:29:04

标签: javascript typescript

考虑电影列表

let 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": 654356453,
        "title": "Bad Boys",
        "boxarts": [{
            width: 200,
            height: 200,
            url: "http://cdn-0.nflximg.com/images/2891/BadBoys200.jpg"
          },
          {
            width: 150,
            height: 200,
            url: "http://cdn-0.nflximg.com/images/2891/BadBoys150.jpg"
          }

        ],
        "url": "http://api.netflix.com/catalog/titles/movies/70111470",
        "rating": 5.0,
        "bookmark": [{
          id: 432534,
          time: 65876586
        }]
      }
    ]
  },
  {
    name: "New Releases",
    videos: [{
        "id": 65432445,
        "title": "The Chamber",
        "boxarts": [{
            width: 150,
            height: 200,
            url: "http://cdn-0.nflximg.com/images/2891/TheChamber150.jpg"
          },
          {
            width: 200,
            height: 200,
            url: "http://cdn-0.nflximg.com/images/2891/TheChamber200.jpg"
          }
        ],
        "url": "http://api.netflix.com/catalog/titles/movies/70111470",
        "rating": 4.0,
        "bookmark": []
      },
      {
        "id": 675465,
        "title": "Fracture",
        "boxarts": [{
            width: 200,
            height: 200,
            url: "http://cdn-0.nflximg.com/images/2891/Fracture200.jpg"
          },
          {
            width: 150,
            height: 200,
            url: "http://cdn-0.nflximg.com/images/2891/Fracture150.jpg"
          },
          {
            width: 300,
            height: 200,
            url: "http://cdn-0.nflximg.com/images/2891/Fracture300.jpg"
          }
        ],
        "url": "http://api.netflix.com/catalog/titles/movies/70111470",
        "rating": 5.0,
        "bookmark": [{
          id: 432534,
          time: 65876586
        }]
      }
    ]
  }
]

movieList由这些接口组成

interface Video {
  id:number;
  title:string;
  boxarts:{width:number,  height:number, url: string}[];
  uri:string;
  rating:number;
  bookmark: {id:number, time:number}[];
}

interface VideoCategory {
  name:string;
  videos: Video[];
} 

我想实现一个函数getBoxArts(),它获取类似于movieLists的类型,并为movieLists中的每个视频返回一个map {id,title,boxart},这样结果中的boxart属性就是url尺寸为150x200px的boxart对象。我只需要使用Flatmap地图和过滤器。但我无法想到的唯一方法是这样的索引:

function getBoxarts(movie) {
  let res = [];
  for (let i = 0; i < movie.length; i++) {
    for (let j = 0; j < movie[i].videos.length; j++) {
      for (let l = 0; l < movie[i].videos[j].boxarts.length; l++) {
        if ((movie[i].videos[j].boxarts[l].width == 150) && (movie[i].videos[j].boxarts[l].height == 200)) {
          res.push({
            id: movie[i].videos[j].id,
            title: movie[i].videos[j].title,
            boxarts: movie[i].videos[j].boxarts[l]
          });
        }
      }

    }

  }
  return res;
}

代码包含3个循环,并不漂亮。

编辑:我已经定义了一个名为flatmap的函数

    const concat = (x,y) =>
         x.concat(y)

    const flatmap = (f,xs) =>
         xs.map(f).reduce(concat, [])

它的作用是获取函数f和数组A作为参数,并返回当f应用于A中的每个元素时由f返回的所有数组的串联。 例如

     Flatmap((x)=>x[0], [[[1,2], [3,4]], [[5,6], [7,8]]]) => [1,2,5,6]

1 个答案:

答案 0 :(得分:0)

您可以使用功能样式并使用array#reducearray#forEacharray#find来过滤掉boxart 150和width 200的height

let 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": 654356453, "title": "Bad Boys", "boxarts": [{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/BadBoys200.jpg" }, { width:150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/BadBoys150.jpg" } ], "url": "http://api.netflix.com/catalog/titles/movies/70111470", "rating": 5.0, "bookmark": [{ id: 432534, time: 65876586 }] } ] }, { name: "New Releases", videos: [{ "id":65432445, "title": "The Chamber", "boxarts": [{ width: 150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/TheChamber150.jpg" }, { width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/TheChamber200.jpg" } ], "url": "http://api.netflix.com/catalog/titles/movies/70111470","rating": 4.0, "bookmark": [] }, { "id": 675465, "title": "Fracture", "boxarts": [{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture200.jpg" }, { width: 150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture150.jpg"}, { width: 300, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture300.jpg" } ], "url": "http://api.netflix.com/catalog/titles/movies/70111470", "rating": 5.0, "bookmark": [{ id: 432534, time: 65876586 }] } ] } ],
    result = movieLists.reduce((r, {videos}) => {
      videos.forEach(({id, title, boxarts}) => {
        let boxart = boxarts.find(({width, height}) => width === 150 && height === 200);
        if(boxart) {
          r.push({id, title, boxarts : boxart});
        }
      });
      return r;
    }, []);
console.log(result);

您可以先展平数组,然后搜索所需的boxart并将其推送到结果数组中。

let 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": 654356453, "title": "Bad Boys", "boxarts": [{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/BadBoys200.jpg" }, { width:150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/BadBoys150.jpg" } ], "url": "http://api.netflix.com/catalog/titles/movies/70111470", "rating": 5.0, "bookmark": [{ id: 432534, time: 65876586 }] } ] }, { name: "New Releases", videos: [{ "id":65432445, "title": "The Chamber", "boxarts": [{ width: 150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/TheChamber150.jpg" }, { width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/TheChamber200.jpg" } ], "url": "http://api.netflix.com/catalog/titles/movies/70111470","rating": 4.0, "bookmark": [] }, { "id": 675465, "title": "Fracture", "boxarts": [{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture200.jpg" }, { width: 150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture150.jpg"}, { width: 300, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture300.jpg" } ], "url": "http://api.netflix.com/catalog/titles/movies/70111470", "rating": 5.0, "bookmark": [{ id: 432534, time: 65876586 }] } ] } ],
    result = [].concat(...movieLists.map(({videos}) => videos))
               .reduce((r,{id,title, boxarts}) => {
                let boxart = boxarts.find(({width, height}) => width === 150 && height === 200);
                if(boxart)
                  r.push({id, title, boxarts: boxart});
                return r;
              }, [])
console.log(result);

let 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": 654356453, "title": "Bad Boys", "boxarts": [{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/BadBoys200.jpg" }, { width:150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/BadBoys150.jpg" } ], "url": "http://api.netflix.com/catalog/titles/movies/70111470", "rating": 5.0, "bookmark": [{ id: 432534, time: 65876586 }] } ] }, { name: "New Releases", videos: [{ "id":65432445, "title": "The Chamber", "boxarts": [{ width: 150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/TheChamber150.jpg" }, { width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/TheChamber200.jpg" } ], "url": "http://api.netflix.com/catalog/titles/movies/70111470","rating": 4.0, "bookmark": [] }, { "id": 675465, "title": "Fracture", "boxarts": [{ width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture200.jpg" }, { width: 150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture150.jpg"}, { width: 300, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture300.jpg" } ], "url": "http://api.netflix.com/catalog/titles/movies/70111470", "rating": 5.0, "bookmark": [{ id: 432534, time: 65876586 }] } ] } ],
    concat = (x,y) => x.concat(y),
    flatmap = (f,xs) => xs.map(f).reduce(concat, []),
    result = flatmap((({videos}) => videos), movieLists)
            .map(({id,title, boxarts}) => {
                let boxart = boxarts.filter(({width, height}) => width === 150 && height === 200);
                if(boxart || boxart.length)
                  return ({id, title, boxarts: boxart[0]});
                else
                  return undefined;
              })
              .filter(o => o)
console.log(result);