在一个对象数组中寻找匹配id的最佳方法是什么?

3

如果我有这个电影id数组

movies = [28, 14, 100, 53, 37]

以及这个对象数组。

genres = [
      {id: 28, name: "Action"},
      {id: 10770, name: "TV Movie"},
      {id: 53, name: "Thriller"},
      {id: 10752, name: "War"},
      {id: 37, name: "Western"}
    ]

我希望返回一个匹配id的数组,例如['动作','惊悚','西部']。
我已经有了一个解决方案,但感觉它可以更好。重构这段代码的最佳方法是什么?谢谢。
genre_array = []
movies.forEach(function(e){
  genres.forEach(function(element){
    if (element.id == e) {
     genre_array.push(element.name)
    } 
  });
});

在Javascript中,我总是建议使用===而不是==,这样可以消除任何类型强制转换的影响。另一件事是要研究不可变方法,例如reduce、map和filter。原因是不可变性有助于通过返回新值而不是改变现有值来减少副作用。 - AHB
6个回答

8
我会将filtermap数组方法结合起来使用。使用filter获取在movies数组中的流派列表,然后使用map将其转换为名称列表。
例如:

const movies = [28, 14, 100, 53, 37]

const genres = [
      {id: 28, name: "Action"},
      {id: 10770, name: "TV Movie"},
      {id: 53, name: "Thriller"},
      {id: 10752, name: "War"},
      {id: 37, name: "Western"}
    ]

// I would like to return an array of the matching ids. example [ 'Action', 'Thriller', 'Western' ].

console.log(genres.filter(g => movies.includes(g.id)).map(g => g.name))


2

首先将array=movies转换为Set(当array=movies的元素数量很多时,这样可以提高性能),然后使用reduce来提取所有匹配项。

let movies = [28, 14, 100, 53, 37, 28]

let genres = [
      {id: 28, name: "Action"},
      {id: 10770, name: "TV Movie"},
      {id: 53, name: "Thriller"},
      {id: 10752, name: "War"},
      {id: 37, name: "Western"}
    ]

let indexes = new Set(movies)

console.log(
  genres.reduce((pre, cur) => {
    indexes.has(cur.id) && pre.push(cur.name)
    return pre
  }, [])
)


1

使用数组减少器将id进行匹配

const movies = [28, 14, 100, 53, 37]

const genres = [
  {id: 28, name: "Action"},
  {id: 10770, name: "TV Movie"},
  {id: 53, name: "Thriller"},
  {id: 10752, name: "War"},
  {id: 37, name: "Western"}
]

let genre_array = genres.reduce((arr, itm) => movies.includes(itm.id) ? arr.concat(itm.name) : arr, [])

console.log(genre_array)


1
简单:

const movies = [28, 14, 100, 53, 37]

const genres = [{
    id: 28,
    name: "Action"
  },
  {
    id: 10770,
    name: "TV Movie"
  },
  {
    id: 53,
    name: "Thriller"
  },
  {
    id: 10752,
    name: "War"
  },
  {
    id: 37,
    name: "Western"
  }
]
let genre_array = [];
genres.forEach(function(element) {
  if (movies.includes(element.id)) {
    genre_array.push(element.name)
  }
});
alert(genre_array);


1

过滤器和映射的简写

const movies = [28, 14, 100, 53, 37],
genres = [
  {id: 28, name: "Action"},
  {id: 10770, name: "TV Movie"},
  {id: 53, name: "Thriller"},
  {id: 10752, name: "War"},
  {id: 37, name: "Western"}
],
genreList = genres  // filter and a map - shorthand
  .filter(({id}) => movies.includes(id))
  .map(({name})  => name);
console.log(genreList);


0
今天早上我遇到了一个非常相似的问题,并花时间解决了可能的一个疏忽,即给定的解决方案会丢失原始数组的顺序。
所以我进行了一些挖掘和与他人讨论(感谢Discord!),我想出了这个解决方案;
  1. 保留原始数组元素的顺序(而不是对象的顺序)。
  2. 清除空值返回并删除任何重复项。
const movies = [37, 28, "bad data", false ,, 53, 53];
const genres = [
        {
            "id": 28,      
            "name": "Action"
        }, {
            "id": 10770,   
            "name": "TV Movie"
        },{
            "id": 53,      
            "name": "Thriller"
        },{
            "id": 10752,   
            "name": "War"
        }, {
            "id": 37,      
            "name": "Western"
        }];

const genreList  = new Set(
movies
    .map(   element       => genres
    .find(  objectElement => objectElement.id === element)?.name)
    .filter(Boolean));

//Return is [ 'Western', 'Action', 'Thriller' ]
console.log(Array.from(genreList));

重要的是要注意返回数组的顺序与原始ID的顺序相匹配。

感谢发布的其他解决方案。有很多方法可以实现很大的成就。我很想听听我的解决方案可能在哪些地方可以进一步改进。


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