2

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}
1

2 Answers 2

4

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)

Sign up to request clarification or add additional context in comments.

5 Comments

you can use id instead of name. I think it might be better idea
@AlexeyZelenin Your point is valid but OP requirement is to compare name
Are you sure about the user part?because i think he has an array of users not a single user object?
@AlanOmar I was also thinking of that but he didn't mentioned anything yet. I just refactored his come into simpler. Lets see how OP respond
Thanks for the responses guys! I think id or name would have been viable, but I was looking to return the whole video object as in Pilchard's solution! (I probably didn't do a great job of explaining myself!) Really appreciate the help though! :)
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.