对数组进行排序,并只保留每天reactjs的最后一个值



我这里有点问题,我有一个数组,看起来像这样:

const input = {
name: 'xy',
lastname: 'yx',
history: [
{ "value": 0.02, "date": "2022-08-02T23:03:22.895Z" }, 
{ "value": 0.04, "date": "2022-08-02T22:03:16.603Z" },
{ "value": 0.08, "date": "2022-08-02T21:03:20.378Z" },
{ "value": 0.02, "date": "2022-08-01T23:03:32.584Z" },
{ "value": 0.04, "date": "2022-08-01T22:03:30.311Z" }]
}                            

但是它比这个例子有更多的数据和日期,我想把它排序到一个新的数组中,只放每天的最新值

所以它看起来是这样的:

const input = {
name: 'xy',
lastname: 'yx',
history: [
{ "value": 0.02, "date": "2022-08-02T23:03:22.895Z" }, 
{ "value": 0.04, "date": "2022-08-02T22:03:16.603Z" },
{ "value": 0.08, "date": "2022-08-02T21:03:20.378Z" },
{ "value": 0.02, "date": "2022-08-01T23:03:32.584Z" },
{ "value": 0.04, "date": "2022-08-01T22:03:30.311Z" }],                   
newHistory: 
{ "value": 0.02, "date": "2022-08-02T23:03:22.895Z" }, 
{ "value": 0.02, "date": "2022-08-01T23:03:32.584Z" }],   
}

我目前对所有日期都进行了排序,但我在做剩下的事情时遇到了麻烦。

由于您已经对数据进行了排序,因此可以使用单个reduce来迭代已排序数据的数组,同时跟踪新的输出数组。

对于每个数据点,将其日期与输出的最后一个元素进行比较。如果年月日部分不相同,则将数据点添加到输出数组中。

以下是用代码编写的步骤:

const input = [
{ "value": 0.02, "date": "2022-08-02T23:03:22.895Z" }, 
{ "value": 0.04, "date": "2022-08-02T22:03:16.603Z" },
{ "value": 0.08, "date": "2022-08-02T21:03:20.378Z" },
{ "value": 0.02, "date": "2022-08-01T23:03:32.584Z" },
{ "value": 0.04, "date": "2022-08-01T22:03:30.311Z" } ];

const output = input.reduce(
(out, current) => {
const lastDate = out.at(-1)?.date.slice(0, 10);
const currentDate = current.date.slice(0, 10);

if (lastDate !== currentDate) {
out.push(current);
}

return out;
},
[]
);
console.log(output);

如果你喜欢一句俏皮话,你也可以这样写:

const input = [
{ "value": 0.02, "date": "2022-08-02T23:03:22.895Z" }, 
{ "value": 0.04, "date": "2022-08-02T22:03:16.603Z" },
{ "value": 0.08, "date": "2022-08-02T21:03:20.378Z" },
{ "value": 0.02, "date": "2022-08-01T23:03:32.584Z" },
{ "value": 0.04, "date": "2022-08-01T22:03:30.311Z" } ];

const output = input.reduce(
(out, current) => out.at(-1)?.date.slice(0, 10) === current.date.slice(0, 10) ? out : out.concat(current),
[]
);
console.log(output);

我认为这肯定是一个问题,将不同的任务拆分为函数有助于使代码更容易理解。

你在一条评论中说,你想根据UTC时间对日历日期进行分组,但(如果你改变主意(下面的代码也允许你选择性地使用系统时区(以及其他一些选项(。

当你阅读时,我已经包含了很多评论来解释,但如果仍有不清楚的地方,请随时在评论中要求澄清。

'use strict';
/** @returns a stringified number with a minimum length */
function padN (n, maxLength = 2, fillString = '0') {
return String(n).padStart(maxLength, fillString);
}
/**
* @returns a default sorting algorithm function
* for an array of objects each having a specific key
*/
function createDefaultSortByObjKey (key, {reverse = false} = {}) {
return reverse
? (oA, oB) => oA[key] > oB[key] ? -1 : oA[key] < oB[key] ? 1 : 0
: (oA, oB) => oA[key] < oB[key] ? -1 : oA[key] > oB[key] ? 1 : 0;
}
/**
* Set the `utc` option to `true` to use UTC
* @returns a date string format like `"20220703"`
*/
function getSerializedYMD (date, {utc = false} = {}) {
const year = utc ? date.getUTCFullYear() : date.getFullYear();
const month = utc ? date.getUTCMonth() : date.getMonth();
const dayOfMonth = utc ? date.getUTCDate() : date.getDate();
return `${year}${padN(month)}${padN(dayOfMonth)}`;
}
/** @pure */
function transform (array, {
newestFirst = false,
parseDates = false,
utc = false,
} = {}) {
// Create a function for sorting dates, sorting by oldest/newest
const sortFn = createDefaultSortByObjKey('date', {reverse: newestFirst});
const sorted = array
// Create actual date objects for every date property value
.map(o => ({...o, date: new Date(o.date)}))
// Sort them
.sort(sortFn);
// This will be used to compare if the current object's date occurred
// on the same date as the previous
let lastKey = '';
// The objects will be stored in inner arrays, grouped by calendar dates
const grouped = [];
for (const obj of sorted) {
const key = getSerializedYMD(obj.date, {utc});
// Create a new inner array group if a new calendar date is encountered
if (key !== lastKey) grouped.push([]);
// Add the object to the current date group
grouped.at(-1).push(obj);
// Update the last key
lastKey = key;
}
// Now just pick one date from each group
return grouped.map(group => {
// Pick the oldest/newest object in the group
const obj = group.at(newestFirst ? 0 : -1);
return parseDates
// Return it directly with the date value as an actual date object
? obj
// Or convert the date back to an ISO string first
: {...obj, date: obj.date.toISOString()};
});
}
const input = {
name: 'xy',
lastname: 'yx',
history: [
{ value: 0.02, date: '2022-08-02T23:03:22.895Z' },
{ value: 0.04, date: '2022-08-02T22:03:16.603Z' },
{ value: 0.08, date: '2022-08-02T21:03:20.378Z' },
{ value: 0.02, date: '2022-08-01T23:03:32.584Z' },
{ value: 0.04, date: '2022-08-01T22:03:30.311Z' },
],
};
const result = {
// Spread in all of the other properties
...input,
// And add a new transformed array from the `history` property
newHistory: transform(input.history, {newestFirst: true, utc: true}),
// You can even use the sorting function to sort the original history if you want:
// history: [...input.history].sort(createDefaultSortByObjKey('date', {reverse: true})),
};
console.log(result);
// You could have also used the options to get a different result variation:
// transform(input.history, {
//   newestFirst: false,
//   parseDates: true,
//   utc: false,
// });

相关内容

最新更新