Dec Burns
Dec Burns

Reputation: 53

Filter array of objects matching values from second array

In my react app I have users that look like this:

{ username: 'admin', genres: [{name: 'Music', id: 1}, {name: 'Art', id: 2}] }

And videos that look like this:

{ title: 'cool video', genres: [{name: 'Music', id: 1}, {name: 'Technology', id: 3}] }

I am trying to write a function that will return an array of the video objects that contain any of the genres inside a single user. So far I have been able to hard code a solution, but it breaks if a user has the wrong number of genres, so I am looking for a neater solution. This is what I have so far:

function filterVideos() {

const userGenres = []

user.genres.forEach(genre => {
  userGenres.push(genre.name)
})

const filteredVideos = videos.filter(video => {

  return video.genres.find(o => o.name === userGenres[0])
   || video.genres.find(o => o.name === userGenres[1])
   || video.genres.find(o => o.name === userGenres[2])
})
return filteredVideos}

Upvotes: 2

Views: 1964

Answers (2)

pilchard
pilchard

Reputation: 12956

If I understand your question, you are looking to return a filtered array of complete video objects which have at least one genre in common with the passed user.

You can simplify the user's genre array to an array of genre names using a single map() call.

const userGenres = user.genres.map(({name}) => name);

It is then a matter of using Array.prototype.some() to determine if any of the video's genres are included in the userGenres array using Array.prototype.includes()

 videos.filter(video => (
    video.genres.some(({name}) => userGenres.includes(name))
  ));

const user = { 
  username: 'admin',
  genres: [{name: 'Music', id: 1}, {name: 'Art', id: 2}] }

const videos = [
  {
    title: 'video1', 
    genres: [{name: 'Music', id: 1}, {name: 'Technology', id: 3}] 
  },
  {
    title: 'video2', 
    genres: [{name: 'Art', id: 1}, {name: 'Technology', id: 3}] 
  },
  {
    title: 'video3', 
    genres: [{name: 'Sports', id: 1}, {name: 'Technology', id: 3}, , {name: 'Skiing', id: 3}] 
  }
]

function filterVideos(user, videos) {

  const userGenres = user.genres.map(({name}) => name);
  
  return videos.filter(video => (
    video.genres.some(({name}) => userGenres.includes(name))
  ));
  
}

console.log(filterVideos(user, videos));

Upvotes: 1

Maheer Ali
Maheer Ali

Reputation: 36594

You can use some() inside filter

const filteredVideos = videos.filter(video => user.genres.some(gen => gen.name === video.name))

const user = { username: 'admin', genres: [{name: 'Music', id: 1}, {name: 'Art', id: 2}] }
const video = { title: 'cool video', genres: [{name: 'Music', id: 1}, {name: 'Technology', id: 3}] };

const res = video.genres.filter(v => user.genres.some(g => g.name === v.name));
console.log(res)

Upvotes: 4

Related Questions