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

时间:2017-04-29 22:56:47

标签: javascript date underscore.js lodash

我试图按日期月份和周来对对象数组进行排序

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)一起使用。

我设法按年,月,年和周对数据进行排序,但我无法弄清楚如何同时对三者进行排序。

感谢您的帮助

4 个答案:

答案 0 :(得分:1)

您可以使用for..of循环,String.prototype.match()RegExp /\d+/一起获取YYYYMM部分"date"适当的价值; Array.prototype.filter()通过比较YYYY-MMfor..ofYYYY连接,将输入数组中对象的"-"MM循环的当前对象相匹配。



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/

答案 1 :(得分:1)

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

如果您每天所处的“每周的一周”概念只是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));

答案 2 :(得分:0)

&#13;
&#13;
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));
&#13;
&#13;
&#13;

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

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

到此:

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

答案 3 :(得分:0)

使用lodash是可行的方法。

&#13;
&#13;
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);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
&#13;
&#13;
&#13;