如何按日期对对象数组进行排序,但最新日期排在第一位?
How to sort array of objects by date but with most current date first?
我有对象数组:
const data = [{
"id": "1",
"effectiveDate": "2023-01-21"
}, {
"id": "2",
"effectiveDate": "2023-02-22"
}, {
"id": "3",
"effectiveDate": "2022-05-04"
}, {
"id": "4",
"effectiveDate": "2022-05-05"
}, {
"id": "5",
"effectiveDate": "2021-01-21"
}, {
"id": "6",
"effectiveDate": "2021-02-22"
}];
我想要的是按照最新日期的对象在索引 0 上的方式对其进行排序的方式,其余对象从最旧的日期到未来的日期按升序排列,如下所示:
[{
"id": "4",
"effectiveDate": "2022-05-05"
}, {
"id": "5",
"effectiveDate": "2021-01-21"
}, {
"id": "6",
"effectiveDate": "2021-02-22"
}, {
"id": "3",
"effectiveDate": "2022-05-04"
}, {
"id": "1",
"effectiveDate": "2023-01-21"
}, {
"id": "2",
"effectiveDate": "2023-02-22"
}]
我排序的方式是:
const orderedDates = data.sort((a, b) => {
const dateCompareResult = new Date(a.effectiveDate) - new Date(b.effectiveDate);
return dateCompareResult;
});
这显然给我的日期从过去的日期到未来的日期升序排列,最新日期介于两者之间。
如何将最新的日期对象移动到索引 0?
function getItemsInAscendingDateOrderAndClosestToNowFirst(arr) {
const time = Date.now();
const [closest, ...rest] = Array
// create a shallow copy in order to
// not mutate the original reference.
.from(arr)
// sort items by date closest to now.
.sort((a, b) => {
const aTime = new Date(a.effectiveDate).getTime();
const bTime = new Date(b.effectiveDate).getTime();
const aDelta = Math.abs(time - aTime);
const bDelta = Math.abs(time - bTime);
return (aDelta - bDelta);
});
return [
closest,
...rest
// sort all other items in ascending date order.
.sort((a, b) =>
new Date(a.effectiveDate).getTime()
- new Date(b.effectiveDate).getTime()
),
];
}
const data = [{
"id": "1",
"effectiveDate": "2023-01-21"
}, {
"id": "2",
"effectiveDate": "2023-02-22"
}, {
"id": "3",
"effectiveDate": "2022-05-04"
}, {
"id": "4",
"effectiveDate": "2022-05-05"
}, {
"id": "5",
"effectiveDate": "2021-01-21"
}, {
"id": "6",
"effectiveDate": "2021-02-22"
}];
const sortedData =
getItemsInAscendingDateOrderAndClosestToNowFirst(data);
console.log({ sortedData });
.as-console-wrapper { min-height: 100%!important; top: 0; }
我认为最简单的方法是从最旧到最新排序,然后将最接近今天的元素移到开头,例如
let data = [{"id": "1","effectiveDate": "2023-01-21"},
{"id": "2","effectiveDate": "2023-02-22"},
{"id": "3","effectiveDate": "2022-05-04"},
{"id": "4","effectiveDate": "2022-05-05"},
{"id": "5","effectiveDate": "2021-01-21"},
{"id": "6","effectiveDate": "2021-02-22"}];
// Sort from oldest to youngest
data.sort((a, b) => b.effectiveDate.localeCompare(a.effectiveDate));
// Get today as milliseconds
let today = new Date().toLocaleDateString('en-CA');
let todayMS = Date.parse(today);
// Get index of closest element to today
let closestIndex = data.reduce((acc, obj, index) => {
let diff = Math.abs(Date.parse(obj.effectiveDate) - todayMS);
return acc.diff > diff? {diff, index} : acc;
}, {diff: Infinity, index:null}).index;
// Move closest element to start of array
data.unshift(data.splice(closestIndex, 1));
console.log(data);
ISO 8601 格式时间戳的好处之一是词法比较会给出正确的结果。如果你不想使用字符串比较那么比较函数可以是:
data.sort((a, b) => Date.parse(b) - Date.parse(a))
但前提是时间戳是 ECMA-262 支持的 3 种格式之一(幸运的是,YYYY-MM-DD 就是这样一种格式)。 :-)
我有对象数组:
const data = [{
"id": "1",
"effectiveDate": "2023-01-21"
}, {
"id": "2",
"effectiveDate": "2023-02-22"
}, {
"id": "3",
"effectiveDate": "2022-05-04"
}, {
"id": "4",
"effectiveDate": "2022-05-05"
}, {
"id": "5",
"effectiveDate": "2021-01-21"
}, {
"id": "6",
"effectiveDate": "2021-02-22"
}];
我想要的是按照最新日期的对象在索引 0 上的方式对其进行排序的方式,其余对象从最旧的日期到未来的日期按升序排列,如下所示:
[{
"id": "4",
"effectiveDate": "2022-05-05"
}, {
"id": "5",
"effectiveDate": "2021-01-21"
}, {
"id": "6",
"effectiveDate": "2021-02-22"
}, {
"id": "3",
"effectiveDate": "2022-05-04"
}, {
"id": "1",
"effectiveDate": "2023-01-21"
}, {
"id": "2",
"effectiveDate": "2023-02-22"
}]
我排序的方式是:
const orderedDates = data.sort((a, b) => {
const dateCompareResult = new Date(a.effectiveDate) - new Date(b.effectiveDate);
return dateCompareResult;
});
这显然给我的日期从过去的日期到未来的日期升序排列,最新日期介于两者之间。 如何将最新的日期对象移动到索引 0?
function getItemsInAscendingDateOrderAndClosestToNowFirst(arr) {
const time = Date.now();
const [closest, ...rest] = Array
// create a shallow copy in order to
// not mutate the original reference.
.from(arr)
// sort items by date closest to now.
.sort((a, b) => {
const aTime = new Date(a.effectiveDate).getTime();
const bTime = new Date(b.effectiveDate).getTime();
const aDelta = Math.abs(time - aTime);
const bDelta = Math.abs(time - bTime);
return (aDelta - bDelta);
});
return [
closest,
...rest
// sort all other items in ascending date order.
.sort((a, b) =>
new Date(a.effectiveDate).getTime()
- new Date(b.effectiveDate).getTime()
),
];
}
const data = [{
"id": "1",
"effectiveDate": "2023-01-21"
}, {
"id": "2",
"effectiveDate": "2023-02-22"
}, {
"id": "3",
"effectiveDate": "2022-05-04"
}, {
"id": "4",
"effectiveDate": "2022-05-05"
}, {
"id": "5",
"effectiveDate": "2021-01-21"
}, {
"id": "6",
"effectiveDate": "2021-02-22"
}];
const sortedData =
getItemsInAscendingDateOrderAndClosestToNowFirst(data);
console.log({ sortedData });
.as-console-wrapper { min-height: 100%!important; top: 0; }
我认为最简单的方法是从最旧到最新排序,然后将最接近今天的元素移到开头,例如
let data = [{"id": "1","effectiveDate": "2023-01-21"},
{"id": "2","effectiveDate": "2023-02-22"},
{"id": "3","effectiveDate": "2022-05-04"},
{"id": "4","effectiveDate": "2022-05-05"},
{"id": "5","effectiveDate": "2021-01-21"},
{"id": "6","effectiveDate": "2021-02-22"}];
// Sort from oldest to youngest
data.sort((a, b) => b.effectiveDate.localeCompare(a.effectiveDate));
// Get today as milliseconds
let today = new Date().toLocaleDateString('en-CA');
let todayMS = Date.parse(today);
// Get index of closest element to today
let closestIndex = data.reduce((acc, obj, index) => {
let diff = Math.abs(Date.parse(obj.effectiveDate) - todayMS);
return acc.diff > diff? {diff, index} : acc;
}, {diff: Infinity, index:null}).index;
// Move closest element to start of array
data.unshift(data.splice(closestIndex, 1));
console.log(data);
ISO 8601 格式时间戳的好处之一是词法比较会给出正确的结果。如果你不想使用字符串比较那么比较函数可以是:
data.sort((a, b) => Date.parse(b) - Date.parse(a))
但前提是时间戳是 ECMA-262 支持的 3 种格式之一(幸运的是,YYYY-MM-DD 就是这样一种格式)。 :-)