I'm trying to sort an object so it doesn't have to do the same loop n times.
Given the following object
movies = [
{
title: "The Lord of the Rings: The Fellowship of the Ring"
year: 2001
},
{
title: "The Lord of the Rings: The Two Towers"
year: 2002
},
{
title: "The Lord of the Rings: The Return of the King"
year: 2003
},
{
title: "A Beautiful Mind"
year: 2001
},
]
I want the movies to be sorted by year and to appear on the screen:
Year 2003
- The Lord of the Rings: The Return of the King
Year 2002
- The Lord of the Rings: The Two Towers
Year 2001
- A Beautiful Mind
- The Lord of the Rings: The Fellowship of the Ring
To do this in vue
I can do something like define an object years = [2003, 2002, 2001]
and then
<div v-for="y in years">
{{ y }}
<div v-for="m in movies">
<div v-if="m.year == y">
{{ m.title }}
</div>
</div>
</div>
However in this way I repeat the v-for
of movies
for the length of the array years
.
So I thought about organizing movies
object in the following way:
moviesByYear = [
2003: [
{
title: "The Lord of the Rings: The Return of the King"
year: 2003
}
],
2002: [
{
title: "The Lord of the Rings: The Two Towers"
year: 2002
}
],
2001: [
{
title: "A Beautiful Mind"
year: 2001
},
{
title: "The Lord of the Rings: The Fellowship of the Ring"
year: 2001
}
]
]
That way I could use
<div v-for="(movies, year) in moviesByYear" :key="year">
<div>{{ year }}</div>
<div v-for="m in movies">
{{ m.title }}
</div>
</div>
Unfortunately, I can't build the moviesByYear
array and I'm not sure it's the correct approach because there are drawbacks to sorting an object by keys. In fact I would need to sort the films both by ascending and descending year.
How could I solve this problem? Is there a better approach than running v-for
n times?
CodePudding user response:
I might be misunderstanding, but first you need to create an array of objects containing year => movie relationships. You can create the reverse sort (ascending) simply by reversing the array. This way you can use a simple iterable v-for, like
<div v-for="year in movieList" >
<div>{{ year.year }}</div>
<div v-for="m in year.movies">
{{ m }}
</div>
</div>
let movies = [{
title: "The Lord of the Rings: The Fellowship of the Ring",
year: 2009
},
{
title: "The Lord of the Rings: The Two Towers",
year: 2002
},
{
title: "The Lord of the Rings: The Return of the King",
year: 2003
},
{
title: "A Beautiful Mind",
year: 2009
},
]
let movieList = movies.reduce((b, a) => {
let index = b.findIndex(f => f.year === a.year);
if (index < 0) b.push({
year: a.year,
movies: [a.title]
});
else b[index].movies.push(a.title);
return b;
}, []).sort((a, b) => b.year - a.year);
console.log(movieList)
console.log('reversed: ', movieList.reverse())