按对象的其中一个字段对对象进行排序以避免重复循环

Sort an object by one of its fields to avoid repeating a loop

我正在尝试对对象进行排序,这样它就不必执行 n 次相同的循环。

给定以下对象

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
    },
]

我希望电影按年份排序并出现在屏幕上:

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

要在 vue 中做到这一点,我可以做一些事情,比如定义一个对象 years = [2003, 2002, 2001] 然后

<div v-for="y in years">
    {{ y }}
    <div v-for="m in movies">
        <div v-if="m.year == y">
            {{ m.title }}
        </div>
    </div>
</div>

但是通过这种方式,我重复 moviesv-for 数组的长度 years

所以我考虑按以下方式组织 movies 对象:

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

那样我可以用

<div v-for="(movies, year) in moviesByYear" :key="year">
    <div>{{ year }}</div>
    <div v-for="m in movies">
        {{ m.title }}
    </div>
</div>

不幸的是,我无法构建 moviesByYear 数组,而且我不确定这是正确的方法,因为按键排序对象存在缺点。事实上,我需要按年份升序和降序对电影进行排序。

我该如何解决这个问题?有没有比运行v-forn次更好的方法?

我可能有误会,但首先你需要创建一个包含 year => movie 关系的对象数组。您可以简单地通过反转数组来创建反向排序(升序)。这样你就可以使用一个简单的可迭代v-for,比如

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