将对象数组按周分组

3

我有一个对象数组,其中包含如下数据

[{
  date: "01-01-2017 00:00:00",
  dataField1: "",
  dataField2: ""
},
{
  date: "01-02-2017 00:00:00",
  dataField1: "",
  dataField2: ""
},
{
  date: "01-15-2017 00:00:00",
  dataField1: "",
  dataField2: ""
},
{
  date: "01-16-2017 00:00:00",
  dataField1: "",
  dataField2: ""
},
{
  date: "01-15-2018 00:00:00",
  dataField1: "",
  dataField2: ""
},
{
  date: "01-16-2018 00:00:00",
  dataField1: "",
  dataField2: ""
}]]

更新:需要按年和月进行排序,而不仅仅是按月份。 我需要将其拆分为一个数组的数组,其中对象按周和年分组。 类似这样:

[
  [{
     date: "01-01-2017 00:00:00",
     dataField1: "",
     dataField2: ""
   },
   {
     date: "01-02-2017 00:00:00",
     dataField1: "",
     dataField2: ""
   }
  ],
  [{
     date: "01-15-2017 00:00:00",
     dataField1: "",
     dataField2: ""
   },
   {
     date: "01-16-2017 00:00:00",
     dataField1: "",
     dataField2: ""
   }],
   [
    {
       date: "01-15-2018 00:00:00",
       dataField1: "",
       dataField2: ""
    },
    {
       date: "01-16-2018 00:00:00",
       dataField1: "",
       dataField2: ""
    }
   ]
]

有没有一种使用JavaScript进行排序的简单且性能良好的方法?

3
如果使用lodash,则使用_.groupBy,否则使用lodash。;) - georg
如果你想坚持使用原生JS,那么你可以遍历数据列表,并将其放入一个对象/映射中,其中键是周数。这不是一个“排序”问题,而是一个“分组”问题。你到目前为止尝试了什么?请发布一些代码。 - TheCrzyMan
2个回答

9
如果您考虑使用类似于momentjs的东西,您可以使用格式函数。通过这种方式,您实际上可以按照任何列在此处的可用日期格式标记进行分组。

function datesGroupByComponent(dates, token) {
  return dates.reduce(function(val, obj) {
    let comp = moment(obj['date'], 'MM/DD/YYYY').format(token);
    (val[comp] = val[comp] || []).push(obj);
    return val;
  }, {});
}

const dates = [
  { date: "01-01-2017 00:00:00" },
  { date: "01-02-2017 00:00:00" },
  { date: "01-15-2017 00:00:00" },
  { date: "01-16-2017 00:00:00" }
];

/* https://momentjs.com/docs/#/displaying/format */

console.log('D', datesGroupByComponent(dates, 'D')); // Day of Month
console.log('w', datesGroupByComponent(dates, 'w')); // Week of Year
console.log('W', datesGroupByComponent(dates, 'W')); // Week of Year (ISO)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>


2
任务有了一些更新。如果我将 YYYY-W 传递给 datesGroupedBy,它可以正常工作。谢谢! - Alexander Demianenko

2
我碰巧有一些代码可以确定ISO-8601周数
从那里开始,只需要将日期字符串分割成可用的部分,然后传递给本地日期构造函数,然后reduce对象到具有键的东西,以便我们可以将日期放入正确的组中,最后,删除键使其成为数组,如您所请求,使用Object.values()

var dates = [{
    date: "01-01-2017 00:00:00",
    dataField1: "",
    dataField2: ""
  },
  {
    date: "01-02-2017 00:00:00",
    dataField1: "",
    dataField2: ""
  },
  {
    date: "01-15-2017 00:00:00",
    dataField1: "",
    dataField2: ""
  },
  {
    date: "01-16-2017 00:00:00",
    dataField1: "",
    dataField2: ""
  }
];

var group = Object.values(dates.reduce((acc, val) => {
  var dateparts = val.date.split(/ |-|:/g);
  var date = new Date(dateparts[2], dateparts[0] - 1, dateparts[1], dateparts[3], dateparts[4], dateparts[5]);
  var weekNo = getISO8601WeekNo(date);
  if (!acc[weekNo]) acc[weekNo] = [];
  acc[weekNo].push(val);
  return acc;
}, {}));

console.log(group);

function getISO8601WeekNo(date) {
  var startDate = new Date(date.getFullYear(), 0);
  var endDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
  while (endDate.getDay() < 6) endDate.setDate(endDate.getDate() + 1);
  endDate = endDate.getTime();
  var weekNo = 0;
  while (startDate.getTime() < endDate) {
    if (startDate.getDay() == 4) weekNo++;
    startDate.setDate(startDate.getDate() + 1);
  }
  return weekNo;
}


非常感谢!你为我节省了很多时间! 只需更改您的正则表达式 var dateparts = val.date.split(/ |-|:/g);var dateparts = val.date.split(/T+|-|:/g); 以支持日期格式,例如 2017-01-04T00:00:00-05:00 - Alexander Demianenko
非常不客气 :D 如果这对你有帮助,请记得点击左边的复选框将其标记为被接受的答案。@AlexAL - I wrestled a bear once.
@occams-razor 取消了勾选标记。刚刚更新,需要按年份排序,而不仅仅是按月份。但解决问题很好 :) - Alexander Demianenko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接