如何从系列中提取连续的几天?

时间:2018-07-06 10:23:00

标签: javascript recursion

我正在尝试编写一个递归函数来查找数组中连续天的开始和结束索引。

这是我的示例输入:

var input =  [
    '2018-06-11',
    '2018-06-12',
    '2018-06-15',
    '2018-06-16',
    '2018-06-17',
    '2018-06-19'
];

我希望我的输出是:

var expectedOutput = [{
        start: '2018-06-11',
        end: '2018-06-12'
    },
    {
        start: '2018-06-15',
        end: '2018-06-17'
    },
    {
        start: '2018-06-19',
        end: '2018-06-19'
    }
];

所以我想找到连续两天的开始/结束日期。

个人日子应该是独立的。

我已经写了一个算法,但是第一天就停止了。

function extractConsecutiveDays(input, index) {

    if (input == null || input.length === 0) {
        return;
    }

    if(isConsecutiveDay(input[index], input[index + 1])) {
        return extractConsecutiveDays(input, index + 1);
    }

    var obj = {
        start: input[0],
        end: input[index]
    };

    input.splice(0, index);
    return obj;
}

这是我的小提琴: https://jsfiddle.net/aubz88/tz24o0fk/

1 个答案:

答案 0 :(得分:1)

我在上面问过为什么您想要一个递归解决方案(这个问题并不真正适合它),并且sounds like您可以接受非递归解决方案。如果是这样,请参阅评论:

function findConsecutive(array) {
    var result = [];
    var current = null;
    // Loop through building up each result, starting a new entry each
    // time we find a non-consecutive day
    array.forEach(function(entry) {
        // If this is the first pass or this entry isn't consecutive with
        // the last, start a new entry
        if (!current || !areConsecutive(current.end, entry)) {
            result.push(current = {
              start: entry,
              end: entry
            });
        } else {
            // It's consecutive, just extend the last one
            current.end = entry;
        }
    });
    return result;
}

实时示例:

var input =  [
    '2018-06-11',
    '2018-06-12',
    '2018-06-15',
    '2018-06-16',
    '2018-06-17',
    '2018-06-19'
];

// I *THINK* this `areConsecutive` implementation is reliable across DST
// boundaries (http://jsfiddle.net/em8xqtc2/3/), but be sure to test...
var ONE_DAY_IN_MILLIS = 86400000;
function toDateUTC(str) {
  var parts = str.split("-");
  return Date.UTC(+parts[0], +parts[1] - 1, +parts[2]);
}
function areConsecutive(a, b) {
  return toDateUTC(b) - toDateUTC(a) == ONE_DAY_IN_MILLIS;
}

function findConsecutive(array) {
    var result = [];
    var current = null;
    // Loop through building up each result, starting a new entry each
    // time we find a non-consecutive day
    array.forEach(function(entry) {
        // If this is the first pass or this entry isn't consecutive with
        // the last, start a new entry
        if (!current || !areConsecutive(current.end, entry)) {
            result.push(current = {
              start: entry,
              end: entry
            });
        } else {
            // It's consecutive, just extend the last one
            current.end = entry;
        }
    });
    return result;
}

var expectedOutput = findConsecutive(input);
console.log(expectedOutput);
.as-console-wrapper {
  max-height: 100% !important;
}

由于您出现在解决方案中,因此我仅在其中使用了ES5级功能。但是,如果使用ES2015 +,则变化不大

const input =  [
    '2018-06-11',
    '2018-06-12',
    '2018-06-15',
    '2018-06-16',
    '2018-06-17',
    '2018-06-19'
];

// I *THINK* this `areConsecutive` implementation is reliable across DST
// boundaries (http://jsfiddle.net/em8xqtc2/3/), but be sure to test...
const ONE_DAY_IN_MILLIS = 86400000;
function toDateUTC(str) {
  const [year, month, day] = str.split("-");
  return Date.UTC(+year, +month - 1, +day);
}
function areConsecutive(a, b) {
  return toDateUTC(b) - toDateUTC(a) == ONE_DAY_IN_MILLIS;
}

function findConsecutive(array) {
    const result = [];
    let current = null;
    // Loop through building up each result, starting a new entry each
    // time we find a non-consecutive day
    for (const entry of array) {
        // If this is the first pass or this entry isn't consecutive with
        // the last, start a new entry
        if (!current || !areConsecutive(current.end, entry)) {
            result.push(current = {
              start: entry,
              end: entry
            });
        } else {
            // It's consecutive, just extend the last one
            current.end = entry;
        }
    }
    return result;
}

const expectedOutput = findConsecutive(input);
console.log(expectedOutput);
.as-console-wrapper {
  max-height: 100% !important;
}