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)
}
});
});
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)
}
});
});
Share
Improve this question
asked Aug 6, 2018 at 21:22
user3015195user3015195
1691 silver badge11 bronze badges
1
|
6 Answers
Reset to default 9I 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))
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
}, [])
)
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)
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);
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);
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;
- Keeps the order of the original array elements (as opposed to the order of the objects).
- 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.
===
over==
in Javascript so that it removes any type cohersion. Another thing would be to look into immutable methods such as reduce, map and filter. Reason being that it immutability helps to reduce side effects by returning new values rather than mutating and altering existing values – AHB Commented Aug 6, 2018 at 21:27