我有以下问题。我有一个数组:
const dates = ["19-June-2019", "18-June-2019", "17-June-2019", "16-June-2019", "14-June-2019"]
我需要生成一个日期数组,该数组在我表示行中的日期之后。 所以:
const datesInRow = ["19-June-2019", "18-June-2019", "17-June-2019", "16-June-2019"]
这是我的初始函数:(isAfter函数= date-fns)
function numberOfDaysInRow(arr) {
if (arr.length === 1) return arr;
let numberOfDaysInRowArr = [];
for (let i = 0; i < arr.length; i++) {
if (isAfter(new Date(arr[i]), new Date(arr[i + 1]))) {
numberOfDaysInRowArr.push(arr[i]);
}
}
return numberOfDaysInRowArr;
}
这仅返回部分答案。例如,如果我在数组中只有两个这样的字符串:
const dates = ["19-June-2019", "18-June-2019"]
它将返回
["19-June-2019"]
这不是我想要的。
答案 0 :(得分:2)
您可以在循环外处理第一个元素,而仅取下一个元素。
function numberOfDaysInRow(arr) {
if (arr.length === 1) return arr;
let numberOfDaysInRowArr = [];
if (isAfter(new Date(arr[0]), new Date(arr[1]))) {
numberOfDaysInRowArr.push(arr[0]);
}
for (let i = 0; i < arr.length; i++) {
if (isAfter(new Date(arr[i]), new Date(arr[i + 1]))) {
numberOfDaysInRowArr.push(arr[i + 1]);
}
}
return numberOfDaysInRowArr;
}
使用带有以下值的state
变量的抽象方法:
0
:初始值或找不到后续日期1
:发现以下日期2
:序列结尾此方法采用整数值而不是日期升序而不是降序。
仅使用找到的第一个连续数据集。
var array = [1, 3, 5, 7, 8, 9, 10, 12, 14],
state = 0,
result = array.filter((v, i, { [i - 1]: prev, [i + 1]: next }) => {
switch (state) {
case 0:
if (v + 1 === next) {
state = 1;
return true;
}
break;
case 1:
if (prev + 1 === v) return true;
state = 3;
break
}
});
console.log(result);
答案 1 :(得分:2)
const dates = ["19-June-2019", "18-June-2019", "17-June-2019", "16-June-2019", "14-June-2019"]
const datesInRow = ["19-June-2019", "18-June-2019", "17-June-2019", "16-June-2019"]
const datesBroken = ["19-June-2019", "18-June-2019", "17-June-2019", "16-June-2019", "10-June-2019", "09-June-2019", "08-June-2019"]
function isAfter(date1, date2) {
return (date1.getTime() - date2.getTime()) == 86400000;
}
function numberOfDaysInRow(arr) {
if (arr.length === 1) return arr;
let numberOfDaysInRowArr = [arr[0]];
for (let i = 0; i < arr.length - 1; i++) {
if (isAfter(new Date(arr[i]), new Date(arr[i + 1]))) {
numberOfDaysInRowArr.push(arr[i + 1]);
} else {
i = arr.length - 1;
}
}
return numberOfDaysInRowArr;
}
console.log(numberOfDaysInRow(dates))
console.log(numberOfDaysInRow(datesInRow))
console.log(numberOfDaysInRow(datesBroken))
您应使用numberOfDaysInRowArr
初始化[arr[0]]
。
然后循环我直到arr.length - 1
。
另外,按arr[i + 1]
而不是arr[i]
。
答案 2 :(得分:1)
可以将每个日期与上一个和下一个日期进行比较,以检查它们是否相隔一天:
const dates = ["6-June-2019", "4-June-2019", "3-June-2019", "1-June-2019"]
const filtered = dates.filter((v, i, a) => new Date(v) - new Date(a[i - 1]) > -1e8
|| new Date(v) - new Date(a[i + 1]) < 1e8 )
console.log( filtered )
要处理多个组并获得最大的组:
const dates = ["23-June-2019", "22-June-2019",
"13-June-2019", "12-June-2019", "11-June-2019",
"2-June-2019", "1-June-2019"];
let start = 0, maxCount = 0;
for (let count = 1, i = dates.length - 1; i >= 0; i--, count++) {
if (i < 1 || new Date(dates[i - 1]) - new Date(dates[i]) > 1e8) {
if (count > maxCount) {
start = i;
maxCount = count;
}
count = 0;
}
}
console.log( dates.slice(start, start + maxCount) );
要找到第一组:
const dates = ["23-June-2019",
"13-June-2019", "12-June-2019",
"3-June-2019", "2-June-2019", "1-June-2019"];
const start = dates.findIndex((v, i, a) => new Date(v) - new Date(a[++i]) < 1e8);
const end = dates.findIndex((v, i, a) => i > start && new Date(v) - new Date(a[++i]) > 1e8);
console.log( dates.slice(start, end + 1) );
答案 3 :(得分:1)
您可以检查是否是您的最后一个元素...
function numberOfDaysInRow(arr) {
if (arr.length === 1) return arr;
let numberOfDaysInRowArr = [];
for (let i = 0; i < arr.length; i++) {
const isTheLastElement = i === arr.length - 1;
const isAfterNext = () => isAfter(new Date(arr[i]), new Date(arr[i + 1]));
if (isTheLastElement || isAfterNext()) {
numberOfDaysInRowArr.push(arr[i]);
}
}
return numberOfDaysInRowArr;
}
现在,如果您提取条件(谓词),则可以使用filter
来编写更简洁的版本...
function isLastElementOrAfterNext(string, index, stringList) {
return index === stringList.length - 1 || isAfter(new Date(string), new Date(stringList[index + 1];
}
function numberOfDaysInRow(arr) {
return arr.filter(isLastElementOrAfterNext);
}
您可以首先使用map
改进此示例,以转换日期中的字符串...
function stringToDate(string) {
return new Date(string);
}
function isLastElementOrAfterNext(date, index, dateList) {
return index === dateList.length - 1 || isAfter(date, dateList[index + 1];
}
function numberOfDaysInRow(arr) {
return arr.map(stringToDate).filter(isLastElementOrAfterNext);
}
答案 4 :(得分:1)
您不应将内置解析器用于时间戳,因为ECMA-262不支持DD-MMM-YYYY格式。另外,date-fns isAfter函数仅告诉您第一个日期是否在第二个日期之后,它不会告诉您多少。更合适的功能是differenceInDays。
date-fns没有自己的解析器,它使用内置的解析器,因此我建议您使用其他库。解析器在其他问题中已经多次涉及,但是OP格式的解析器并不困难。
因此,只需从第一个日期开始,直到到达数组末尾,或者获得比上一个日期早一天以上的日期即可停止,例如
// Parser for format DD-MMM-YYYY
// Does not validate date
function parseDMY(s) {
let months = 'jan feb mar apr may jun jul aug sep oct nov dec'.split(' ');
let b = s.split('-');
return new Date(b[2], months.indexOf(b[1].toLowerCase().substr(0,3)), b[0]);
}
// Return true if d1 is the day before d0
// where d0, d1 are Dates
function isPreviousDay(d0, d1) {
// Copy dates and set to 00:00:00
let t0 = new Date(d0);
t0.setHours(0,0,0,0);
let t1 = new Date(d1);
t1.setHours(0,0,0,0);
// Set t0 to previous day
t0.setDate(t0.getDate() - 1);
// See if they now have the same time value
return t0.getTime() == t1.getTime();
}
function getContiguous(dates) {
// Get timestamps as array of Dates
let arr = dates.map(parseDMY);
// Result starts with first timestamp
let result = [dates[0]];
// Stop comparing at second last date
let len = dates.length - 2
let i = 0;
// While each date is the day before the current date,
// add its timestamp to the result array
while (i<len && isPreviousDay(arr[i], arr[i+1])) {
result.push(dates[i+1]);
i++;
}
return result;
}
let dates = ["19-June-2019", "18-June-2019", "17-June-2019", "16-June-2019", "14-June-2019"];
console.log(getContiguous(dates));
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.30.1/date_fns.min.js"></script>
我附加了date-fns库,但是它似乎无法正确加载,因此我编写了一个定制的 isPreviousDay 函数。
答案 5 :(得分:0)
if (isAfter(new Date(arr[i]), new Date(arr[i + 1]))) {
numberOfDaysInRowArr.push(arr[i]);
}
如果arr [i]是数组中的最后一个元素,则arr [i + 1]将是未定义的,并且不会将任何内容推送到numberOfDaysInRowArr。