user8116198
user8116198

Reputation:

Filter JavaScript array based on object property from another array

I have 2 arrays in JavaScript. One of which needs filtering based on a property from the other one.

I have a movies list such as this:

[
  {
    id: 1,
    type: 'movies',
    attributes: {
      name: 'Batman'
    }
  },
  {
    id: 2,
    type: 'movies',
    attributes: {
      name: 'Spiderman'
    }
  },
  ...
]

I then have another array which contains movies that a user has watched but they are within a nested object within the array as a relationship following the JSON API spec.

[
  {
    id: '1',
    type: 'moviesWatched',
    attributes: {
      comment: 'Excellent film, would recommend to anyone who loves a action film!'
    },
    relationships: {
      movie: {
        data: {
           type: 'movies',
           id: 2
        }
      }
    }
  }
]

What I need to achieve is I need to cross reference the id from watchList[].relationships.movie.data.id with the first array. Obviously, this list is a lot longer in production but what I am hoping to achieve is to have a full list of movies which the use has watched with the name of the movie based off 2 arrays formatted like this to save me having to store needless data inside of the database.

The outcome of the array would be something along the lines of...

[
  {
    id: 1,
    type: 'movies',
    attributes: {
       name: 'Batman'
    },
    meta: {
      watched: false
    }
  },
  {
    id: 2,
    type: 'movies',
    attributes: {
      name: 'Spiderman'
    },
    meta: {
      watched: true
    }
  }
]

Here is what I have currently, which is working but I don't know if there is a better way to go about it...

movies.map((movie) => {
    const watched = watchedMovies.find((searchable) => {
        return searchable.relationships.movie.data.id === searchable.id;
    });

    movie.meta.watched = watched || false;

    return movie;
});

Upvotes: 1

Views: 122

Answers (1)

slider
slider

Reputation: 12990

Since you said the list can be long, you can extract the "watched" movie ids to a Set and then set the meta.watched property of a movie based on whether or not its id is in the set:

const movies = [{
    id: 1,
    type: 'movies',
    attributes: {
      name: 'Batman'
    }
  },
  {
    id: 2,
    type: 'movies',
    attributes: {
      name: 'Spiderman'
    }
  }
];

const watched = [{
  id: '1',
  type: 'moviesWatched',
  attributes: {
    comment: 'Excellent film, would recommend to anyone who loves a action film!'
  },
  relationships: {
    movie: {
      data: {
        type: 'movies',
        id: 2
      }
    }
  }
}];

const watchedSet = new Set(watched.map(m => m.relationships.movie.data.id));
movies.forEach(movie => movie.meta = {watched: watchedSet.has(movie.id)});

console.log(movies);

Upvotes: 3

Related Questions