user3015195
user3015195

Reputation: 169

Best way to find matching id's in an array of objects?

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

Upvotes: 4

Views: 9533

Answers (6)

Karlstens
Karlstens

Reputation: 13

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. 🏆 I would love to hear of where my solution could possibly be further improved.

Upvotes: 0

mplungjan
mplungjan

Reputation: 178079

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

Upvotes: 1

CRice
CRice

Reputation: 32176

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

Upvotes: 9

Sphinx
Sphinx

Reputation: 10729

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

Upvotes: 2

Schws
Schws

Reputation: 91

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

Upvotes: 1

Get Off My Lawn
Get Off My Lawn

Reputation: 36311

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)

Upvotes: 1

Related Questions