Reputation: 169
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
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;
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
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
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
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
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
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