按日期将对象数组分组到年和月

问题描述 投票:0回答:3

给定以下对象数组:

[{
    "id": 1,
    "name": "random_name1",
    "published_at": "2021-01-16T08:52:24.408Z",
},
{
    "id": 2,
    "name": "random_name2",
    "published_at": "2022-02-16T08:52:24.408Z",
},
{
    "id": 3,
    "name": "random_name3",
    "published_at": "2020-04-16T08:52:24.408Z",
},
{
    "id": 4,
    "name": "random_name4",
    "published_at": "2020-04-16T08:52:24.408Z",
},
{
    "id": 5,
    "name": "random_name5",
    "published_at": "2022-05-16T08:52:24.408Z",
}
]

我需要按年和月对嵌套对象(降序)的一个数组中的项目进行分组,结果应该是:

 [
  {
    year: '2022',
    months: [
      {
        month: '5',
        items: [
          {
            id: '5',
            name: 'random_name5'
          }
        ]
      },
      {
        month: '2',
        items: [
          {
            id: '2',
            name: 'random_name2'
          }
        ]
      }
    ]
  },
  {
    year: '2021',
    months: [
      {
        month: '1',
        items: [
          {
            id: '1',
            name: 'random_name1'
          }
        ]
      },
      {
        month: '2',
        items: [
          {
            id: '2',
            name: 'random_name2'
          }
        ]
      }
    ]
  },
  {
    year: '2020',
    months: [
      {
        month: '4',
        items: [
          {
            id: '3',
            name: 'random_name3'
          },
          {
            id: '4',
            name: 'random_name4'
          }
        ]
      }
    ]
  }
];

我尝试过以下方法:

items = [...new Set(items.map((item) => parseInt(item.published_at.split('-')[0])))].map((year) => [
  {
    year: year,
    months: [
      ...new Set(
        items
          .filter((item) => parseInt(item.published_at.split('-')[0]) === year)
          .map((item) => parseInt(item.published_at.split('-')[1]))
      )
    ].map((month) => [
      {
        month: month,
        items: items.filter(
          (item) => parseInt(item.published_at.split('-')[0]) === year && parseInt(item.published_at.split('-')[1]) === month
        )
      }
    ])
  }
]);

return items

上述解决方案的问题在于,它将创建一个像这样的二维数组(月份也是二维的):

[
  [ { year: 2022, months: [Array] } ],
  [ { year: 2021, months: [Array] } ],
  [ { year: 2020, months: [Array] } ],
  [ { year: 2019, months: [Array] } ],
  [ { year: 2018, months: [Array] } ]
]

如何解决这个问题?

javascript arrays sorting datetime object
3个回答
1
投票

如果您获得了唯一的年月列表,您可以使用它来映射您的对象

const items = [{ "id": 1,"name": "random_name1","published_at": "2021-01-16T08:52:24.408Z", },
{ "id": 2, "name": "random_name2", "published_at": "2022-02-16T08:52:24.408Z",},
{ "id": 3, "name": "random_name3","published_at": "2020-04-16T08:52:24.408Z",},
{"id": 4, "name": "random_name4", "published_at": "2020-04-16T08:52:24.408Z",},
{ "id": 5, "name": "random_name5", "published_at": "2022-05-16T08:52:24.408Z",}]
let uniqueYearMonths = [... new Set(items.map(x => x.published_at.substring(0,7)))];
let results = [... new Set(items.map(x => x.published_at.substring(0,4)))]
  .map(year => ({
    year: year,
    months: uniqueYearMonths
      .filter(ym => ym.startsWith(year))
      .map(ym => ({ 
        month: ym.substring(5,7),
        items: items
          .filter(item => item.published_at.startsWith(ym))
          .map(item => ({
            id: item.id,
            name: item.name
          }))
      }))
    }));

console.log(results);


1
投票

假设您的数组为

data
,您可以使用
map
reduce
等数组方法执行某些操作。

像这样:

const groupedByYear = data.map((e) => ({ ...e, published_at: new Date(e.published_at) }))
.reduce((acc, e) => {
  const year = e.published_at.getFullYear();
  const month = e.published_at.getMonth() + 1;
  if (!acc[year]) acc[year] = { year };
  if (!acc[year][month]) acc[year][month] = [];
  acc[year][month] = e;
  return acc;
}, {})

const result = Object.values(groupedByYear).reduce((acc, e) => {
  const { year, ...months } = e;
  acc.push({ year: year, months: months });
  return acc;
}, [])

这是一个示例,可能不是执行此操作的最佳方法。它只是为了向您展示数据转换的路径。

首先

data.map
能够对日期进行操作。然后使用
reduce
对数据进行分组(此处使用对象)。然后从对象值创建一个数组以匹配您想要的输出。

与您展示的解决方案相比,其优点是限制了迭代数组的次数。为了获得更好的性能,避免在数组上迭代太多时间总是一个好主意。


0
投票

解决这个问题的方法有很多;人们也可以考虑这种做法。我意识到我入党很晚,但希望我仍然可以通过分享想法为社区做出贡献,并通过反馈改进我的思维方式。

const items = [{ "id": 1,"name": "random_name1","published_at": "2021-01- 16T08:52:24.408Z", },
{ "id": 2, "name": "random_name2", "published_at": "2022-02-16T08:52:24.408Z",},
{ "id": 3, "name": "random_name3","published_at": "2020-04-16T08:52:24.408Z",},
{ "id": 4, "name": "random_name4","published_at": "2020-04-26T08:52:24.408Z",},
{"id": 5, "name": "random_name5", "published_at": "2020-04-21T08:52:24.408Z",},
{ "id": 6, "name": "random_name6", "published_at": "2022-05-16T08:52:24.408Z",}];


function groupYearAndMonth(items: any[], key: string) { 
    return [
      ...new Set(
        items.map(item => new Date(item[key]).getFullYear().toString()) // it fetches unique years
      )
    ].map( year => ({ 
        year, // assign years
        months: items.filter( e => new Date(e[key]).getFullYear().toString() === year) // filters months 
        .reduce((acc, item, index) => {
          const month = (new Date(item[key]).getMonth() + 1).toString(); 
          if (!acc[month]) {
            acc[month] = [];
          }
          acc[month][index] = item;

          return acc;
        }, {} )       
      })
     )
  };

console.log(groupYearAndMonth(items, 'published_at'));
© www.soinside.com 2019 - 2024. All rights reserved.