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.groupBy
与 return 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>
我正在尝试按日期、月份和星期对对象数组进行排序
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.groupBy
与 return 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>