[
0: {date: "02-04-2020", count: 1}
1: {date: "16-04-2020", count: 2}
2: {date: "10-04-2020", count: 1}
3: {date: "15-04-2020", count: 4}
4: {date: "04-04-2020", count: 4}
]
从上面的对象数组中,我需要根据日期对它们进行排序,并按以下方式获取输出
[
0: {date: "02-04-2020", count: 1}
1: {date: "04-04-2020", count: 4}
2: {date: "10-04-2020", count: 1}
3: {date: "15-04-2020", count: 4}
4: {date: "16-04-2020", count: 2}
]
我尝试使用以下方法
const sorted_array = data
.slice()
.sort(
(a, b) => new Date(a.date).valueOf() - new Date(b.date).valueOf()
);
我在排序前使用了.slice,因为出现错误Cannot assign to read only property '0' of object '[object Array]
,所以我引用了Error while sorting array of objects Cannot assign to read only property '2' of object '[object Array]'并添加了slice。
但是排序没有正确完成,我需要一些帮助来解决。谢谢。
答案 0 :(得分:2)
您可能会遇到new Date(...)
不能处理这种格式的字符串的问题,因为它不是标准格式。 new Date("02-04-2020")
将其解释为2020年2月4日,并且new Date("16-04-2020")
产生错误。此处似乎使用美国日期格式,而我们日后使用前一个月。
如果您的日期格式为yyyy-mm-dd
,则new Date(...)
可以正常使用,因此,如果您能够进行更改,那将是最顺畅的路线。如果您无法更改格式,则需要考虑更改排序方式:
const sorted_array = data
.map(addSortableColumn)
.sort(bySortColumn)
.map(removeSortableColumn);
function addSortableColumn(item) {
const [day, month, year] = item.date.split('-');
return { ...item, _sortBy: year + month + day };
}
function bySortColumn(a, b) {
return a._sortBy.localeCompare(b._sortBy);
}
function removeSortableColumn(item) {
const { _sortBy, ...otherProps } = item;
return otherProps;
}
(如果您不想删除排序列,则可以跳过最后一步)
更新
如果您需要保留对象原型,则正确地指出,传播语法会破坏这一点。我实际上更喜欢的另一种方法是将排序列存储在单独的映射中。之所以要存储它,是为了避免需要多次计算排序键。
const sortKeys = new Map();
const sorted_array = data.slice().sort(byDDMMYYYY);
function byDDMMYYYY(a, b) {
return getSortKey(a).localeCompare(getSortKey(b));
}
function getSortKey(item) {
let key = sortKeys.get(item);
if (!key) {
const [day, month, year] = item.date.split('-');
key = year + month + day;
sortKeys.set(item, key);
}
return key;
}
答案 1 :(得分:2)
有关您的错误的解释,请参见@Jacob的答案。这是使用正则表达式将日期更改为正确格式的替代解决方案:
const pattern = /(\d{2})-(\d{2})-(\d{4})/;
const repl = "$3-$2-$1";
const sorted_array = data
.slice()
.sort(
(a, b) => new Date(a.date.replace(pattern, repl)) -
new Date(b.date.replace(pattern, repl))
);
还请注意,您不需要比较valueOf()
中的Date
,Date
的算术已经很重载,可以对对象进行本机比较。
编辑:根据specification,将repl
更改为与ISO 8601兼容的YYYY-MM-DD格式。
答案 2 :(得分:1)
您的日期格式不正确。 DD-MM-YYYY是无效的日期格式。
new Date("15-04-2020")
将返回无效日期
您需要将日期转换为ISO日期格式YYYY-MM-DD according to the specification。
const data = [
{_id: "02-04-2020", count: 1},
{_id: "16-04-2020", count: 2},
{_id: "10-04-2020", count: 1},
{_id: "15-04-2020", count: 4},
{_id: "04-04-2020", count: 4},
];
console.log("Original Data: ", data);
// Something like that.
const dataSorted = data.slice().sort((a, b) => {
const [dayA, monthA, yearA] = a._id.split("-");
const [dayB, monthB, yearB] = b._id.split("-");
return new Date(`${yearA}-${monthA}-${dayA}`)
- new Date(`${yearB}-${monthB}-${dayB}`)
});
console.log("Data sorted by date: ", dataSorted);