最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Best way to find matching id's in an array of objects? - Stack Overflow

programmeradmin9浏览0评论

if I have this array of movie ids

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

and this array of objects.

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' ].

I have a solution already but feel that it could be better. What is the best way to refactor this code? Thanks.

genre_array = []
movies.forEach(function(e){
  genres.forEach(function(element){
    if (element.id == e) {
     genre_array.push(element.name)
    } 
  });
});

if I have this array of movie ids

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

and this array of objects.

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' ].

I have a solution already but feel that it could be better. What is the best way to refactor this code? Thanks.

genre_array = []
movies.forEach(function(e){
  genres.forEach(function(element){
    if (element.id == e) {
     genre_array.push(element.name)
    } 
  });
});
Share Improve this question asked Aug 6, 2018 at 21:22 user3015195user3015195 1691 silver badge11 bronze badges 1
  • I'd always recommend === over == in Javascript so that it removes any type cohersion. Another thing would be to look into immutable methods such as reduce, map and filter. Reason being that it immutability helps to reduce side effects by returning new values rather than mutating and altering existing values – AHB Commented Aug 6, 2018 at 21:27
Add a comment  | 

6 Answers 6

Reset to default 9

I would combine the filter and map array methods. Use filter to get a list of genres that are in your movies array, then use map to convert that to a list of names.

Example:

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))

Convert array=movies to Set first (it will improve performances when array=movies has a ton of elements), then use reduce to pull out all match items.

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
  }, [])
)

Use an array reducer to match ids together

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)

Simple:

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);

Filter and map shorthand

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);

I bumped into a very similar problem this morning and took time out to address one possible oversight, in that the order of the original array is lost with the given solutions.

So I did some digging around and discussion with others (thanks discord!), I've come up with this solution that;

  1. Keeps the order of the original array elements (as opposed to the order of the objects).
  2. Cleanses null-ish returns and removes any dupes.
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));

Importantly, note how the order of the returned array matches the order of the original IDs.

Appreciated the other solutions posted. There are so many ways to achieve so much greatness.

发布评论

评论列表(0)

  1. 暂无评论