Javascript - 按年月日分组的对象数组

Javascript - Array of objects group by year, month and date

我正在尝试按日期、月份和星期对对象数组进行排序

myArray : [
            {'name' : 'example1', 'date' : '2011-01-01'},
            {'name' : 'example1', 'date' : '2011-01-02'},
            {'name' : 'example1', 'date' : '2011-02-02'},
            {'name' : 'example1', 'date' : '2011-02-15'},
            {'name' : 'example1', 'date' : '2011-02-17'},
            {'name' : 'example1', 'date' : '2012-01-01'},
            {'name' : 'example1', 'date' : '2012-03-03'},
]

我希望有这样的结果:

result : [{
                    '2011': { // Year 2011
                        '01': { // January
                            '01' : [ // First week of January
                                {'name' : 'example1', 'date' : '2011-01-01'},
                                {'name' : 'example1', 'date' : '2011-01-02'},
                            ]
                        },
                        '02' : { // February
                            '01' : [ // First week of February
                                {'name' : 'example1', 'date' : '2011-02-02'},
                            ],
                            '03' : [
                                {'name' : 'example1', 'date' : '2011-02-15'},
                                {'name' : 'example1', 'date' : '2011-02-17'},
                            ]
                        }
                    },
                    '2012' : { // Year 2012
                        '01' : { // January
                            '01': [ // First week of January
                                {'name': 'example1', 'date': '2012-01-01'}
                            ]
                        },
                        '03': { // March
                            '01' : [ // First week of March
                                {'name' : 'example1', 'date' : '2012-03-03'},
                            ]
                        }
                    }
                }]

我将 lodash.groupByreturn getISOWeek(obj.date)return getMonth(obj.date)return getYear(obj.date) 一起使用。

我设法按年和月、年和周对数据进行排序,但我不知道如何同时对这三个进行排序。

感谢您的帮助

function group(arr) {
  return arr.reduce((r, o) => {
    var p = o.date.split("-");                             // get the parts: year, month and day
    var week = Math.floor(p.pop() / 7) + 1;                // calculate the week number (Math.floor(day / 7) + 1) and remove day from the parts array (p.pop())
    var month = p.reduce((o, p) => o[p] = o[p] || {}, r);  // get the month object (first, get the year object (if not create one), then get the month object (if not create one)
    if(month[week]) month[week].push(o);                   // if there is an array for this week in the month object, then push this object o into that array
    else month[week] = [o];                                // otherwise create a new array for this week that initially contains the object o
    return r;
  }, {});
}


let array = [{"name":"example1","date":"2011-01-01"},{"name":"example1","date":"2011-01-02"},{"name":"example1","date":"2011-02-02"},{"name":"example1","date":"2011-02-15"},{"name":"example1","date":"2011-02-17"},{"name":"example1","date":"2012-01-01"},{"name":"example1","date":"2012-03-03"}];

console.log(group(array));

如果您希望周数采用这种格式 "01", "02", ... 而不是 "1"; "2", ...,请更改此行:

var week = Math.floor(p.pop() / 7) + 1;

对此:

var week = "0" + Math.floor(p.pop() / 7) + 1;

您可以使用 for..of 循环,String.prototype.match()RegExp /\d+/ 得到 YYYY,以及 [=17] 的 MM 部分=] 属性 值; Array.prototype.filter() 通过将 YYYY"-"MM 进行比较,将输入数组中的对象 YYYY-MM 匹配到 for..of 循环中的当前对象。

const myArray = [
  {'name' : 'example1', 'date' : '2011-01-01'},
  {'name' : 'example1', 'date' : '2011-01-02'},
  {'name' : 'example1', 'date' : '2011-02-02'},
  {'name' : 'example1', 'date' : '2011-02-15'},
  {'name' : 'example1', 'date' : '2011-02-17'},
  {'name' : 'example1', 'date' : '2012-01-01'},
  {'name' : 'example1', 'date' : '2012-03-03'},
];

let res = {};

let fn = (year, month, o = res, array = myArray) => {
  o[year][month] = {
    [month]: array.filter(({date: d}) => `${year}-${month}` === d.slice(0, 7))
  };
}

for (let {date} of myArray) {
  let [year, month] = date.match(/\d+/g);
  if (!res[year]) res[year] = {};
  fn(year, month)
}

console.log(res);

jsfiddle https://jsfiddle.net/sd7e9Lp7/3/

从你的问题中确实不清楚你在追求什么。 ISO 周数基于年而不是月,例如2011-01-01 属于 2010 年的最后一周,而不是 2011 年的第一周。您确实不能按月和 ISO 周数组合分组,因为每年大约有 10 周将在一个月开始并在另一个月结束。

如果您对 "week of the month" 的一天只是 Math.ceil(day number / 7) 的概念,那么您可以将其分组,注意像 2016 年 2 月 29 日这样的日期将是第 5 周的唯一一天当年二月

var data = [
  {'name' : 'example1', 'date' : '2011-01-01'},
  {'name' : 'example1', 'date' : '2011-01-02'},
  {'name' : 'example1', 'date' : '2011-02-02'},
  {'name' : 'example1', 'date' : '2011-02-15'},
  {'name' : 'example1', 'date' : '2011-02-17'},
  {'name' : 'example1', 'date' : '2012-01-01'},
  {'name' : 'example1', 'date' : '2012-03-03'},
];

function groupByMonthWeek(data) {
  var year, month, week
  return data.reduce(function (acc, obj) {
    var b = obj.date.split(/\D/);
    
    // Get custom week number, zero padded
    var weekNum = '0' + Math.ceil(b[2]/7);

    // Add year if not already present
    if (!acc[b[0]]) acc[b[0]] = {};
    year = acc[b[0]];
    
    // Add month if not already present
    if (!year[b[1]]) year[b[1]] = {};
    month = year[b[1]];
    
    // Add week if not already present
    if (!month[weekNum]) month[weekNum] = [];

    // Add object to  week
    month[weekNum].push(obj);

    return acc;    
  }, Object.create(null));
}

console.log(groupByMonthWeek(data));

如果你混淆了,可以压缩为以下内容(但我不建议实际使用它):

var data = [
  {'name' : 'example1', 'date' : '2011-01-01'},
  {'name' : 'example1', 'date' : '2011-01-02'},
  {'name' : 'example1', 'date' : '2011-02-02'},
  {'name' : 'example1', 'date' : '2011-02-15'},
  {'name' : 'example1', 'date' : '2011-02-17'},
  {'name' : 'example1', 'date' : '2012-01-01'},
  {'name' : 'example1', 'date' : '2012-03-03'},
];

function groupByMonthWeek(data) {
  return data.reduce((acc, obj) => {
    var [y, m, d] = obj.date.split(/\D/);
    [y, m, '0'+Math.ceil(d/7)].reduce((a,v,i) => a[v] || (a[v] = i < 2 ? {} : []), acc).push(obj);
    return acc;
  }, Object.create(null));
}

console.log(groupByMonthWeek(data));

使用 lodash 是正确的选择。

var myArray = [
  {'name' : 'example1', 'date' : '2011-01-01'},
  {'name' : 'example1', 'date' : '2011-01-02'},
  {'name' : 'example1', 'date' : '2011-02-02'},
  {'name' : 'example1', 'date' : '2011-02-15'},
  {'name' : 'example1', 'date' : '2011-02-17'},
  {'name' : 'example1', 'date' : '2012-01-01'},
  {'name' : 'example1', 'date' : '2012-03-03'},
];

var orderedByMonths = _.groupBy(myArray, function(element) {
                          return element.date.substring(0,7);
                      });
            
var orderedByYears =  _.groupBy(orderedByMonths, function(month) {
                          return month[0].date.substring(0,4);
                      });

console.log(orderedByYears);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>