从日期开始创建一系列日期名称?

时间:2018-05-18 15:51:44

标签: javascript

我有一系列日期,我想转换为更漂亮的字符串格式。相应的日期名称必须显示为范围。

以下是一个例子:

// 0 is Sunday, 6 is Saturday

days = [0,1,2,4,5];
// Should be ["Sunday-Tuesday", "Thursday-Friday"]

days = [0,1,3,5,6]
// Should be ["Friday-Monday", "Wednesday"]
// note that this wraps around!!

我已经尝试了有些成功,但它没有包装。它也是丑陋,imo。

let result = [];
let build = "";
let previous = -10;
let days = [0,1,3,5,6];

for(let i=0;i < days.length; i++) {
    let d = parseInt(days[i]);

    if (d !== previous+1 && i > 0) {
        build = build.slice(1).split(",");
        if (build.length == 1) 
            build = build[0];
        else if (build.length > 0) {
           build = build[0] + "-" + build[build.length-1];
        }
        result.push(build);
        build = "";
    }

    build = build + "," + getDayName(d);

    if (i === days.length-1) {
        build = build.slice(1).split(",");
        if (build.length == 1) 
            build = build[0];
        else if (build.length > 0) {
           build = build[0] + "-" + build[build.length-1];
        }
        result.push(build);
    }
    previous = d;
}

这只会打印出Array [ "Sunday-Monday", "Wednesday", "Friday-Saturday" ]

我怎样才能让日子环绕?有没有更清洁的方法呢?

3 个答案:

答案 0 :(得分:0)

如果将问题分成以下三个步骤,它将变得简单。

  1. 分块为连续元素,例如[[0, 1], [3], [5, 6]]
  2. 处理环绕,例如[[5, 6, 0, 1], [3]]
  3. 转换为字符串,以便['Friday-Monday', 'Wednesday']
  4. &#13;
    &#13;
    const convert = dayNumbers => {
      // 1. chunking into consecutive elements, such that [[0, 1], [3], [5, 6]]
      let chunks = []
      dayNumbers.forEach(num => {
        if (chunks.length === 0) chunks.unshift([num])
        else if (chunks[0][0] === num - 1) chunks[0].unshift(num)
        else chunks.unshift([num])
      })
      chunks = chunks.map(c => c.reverse()).reverse()
    
      // 2. deal with wrap around, such that [[5, 6, 0, 1], [3]]
      let chunksLength = chunks.length
      if (chunksLength >= 2) {
        let lastChunk = chunks[chunksLength - 1]
        if (chunks[0][0] === 0 && lastChunk[lastChunk.length - 1] === 6) {
          chunks[0] = lastChunk.concat(chunks[0])
          chunks = chunks.splice(0, chunksLength - 1)
        }
      }
    
      // 3. convert to string, such that ['Friday-Monday', 'Wednesday']
      const dayNames = [
        'Sunday', 'Monday', 'Tuesday', 'Wednesday',
        'Thursday', 'Friday', 'Saturday'
      ]
      const result = chunks.map(c => {
        if (c.length === 1) return dayNames[c[0]]
        else return dayNames[c[0]] + '-' + dayNames[c[c.length - 1]]
      })
    
      return result
    }
    
    console.log(convert([0, 1, 2, 4, 5])) // ['Sunday-Tuesday', 'Thursday-Friday']
    console.log(convert([0, 1, 3, 5, 6])) // ['Friday-Monday', 'Wednesday']
    &#13;
    &#13;
    &#13;

答案 1 :(得分:0)

我将问题分解为两个步骤:

  • 查找数字序列中的连续范围
  • 将已知的连续范围转换为漂亮的日间范围

此处附带的代码就是这样做的。 groupRanges查看任何范围,通过它将项目分组到连续范围。这意味着它将[0, 1, 2, 4, 5]转换为[[0, 1, 2], [4, 5]]

请注意,如果您提供[5, 0, 1, 2, 4],则会忽略45 连续的事实。如果您希望将其视为连续的,则应在传递之前对其进行排序。

prettyRange只处理以下三种情况:

  • 范围为空(返回空字符串)
  • 范围有一个项目(返回单个项目的人类可读版本)
  • 范围包含多个项目(假设范围是连续范围,并通过执行 -
  • 制作人类可读的版本

groupRanges函数使用Array.reduce作为(我认为)一个干净的解决方案。

&#13;
&#13;
const days1 = [0,1,2,4,5];
const days2 = [0,1,3,5,6];
const days3 = [0,2];
const days4 = [5,1,4];
const days5 = [4];
const daysVariants = [days1, days2, days3, days4, days5];

/**
 * @param {number[]} numbers - An array of numbers from 0-6
 * @return {number[][]} An array of an array of numbers. Each array of numbers will be consecutive in ascending order
 */
function groupRanges(numbers) {
  // Loop over numbers, building an array as we go starting with [].
  return numbers.reduce((ranges, next) => {
    // It's our first number so just return a single-item range
    if (ranges.length <= 0) return [[next]];
    const lastRange = last(ranges);
    const lastNumber = last(lastRange);
    // Next number is consecutive to the last number in the last-seen range, so we should add it to that range
    if (next - lastNumber === 1) return [...ranges.slice(0, -1), [...lastRange, next]]
    // Next number is _not_ consecutive so we add a new single-item range
    return [...ranges, [next]];
  }, []);
}

function last(array) {
  return array[array.length - 1];
}

daysVariants
  .map(groupRanges)
  .forEach(i => console.log(i));
  
const DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
function prettyRange(range) {
  if (range.length === 0) return '';
  if (range.length === 1) return DAYS[range[0]];
  return DAYS[range[0]] + '-' + DAYS[last(range)];
}

daysVariants
  .map(groupRanges)
  .forEach(ranges => ranges.map(prettyRange).forEach(i => console.log(i)));
&#13;
&#13;
&#13;

答案 2 :(得分:0)

您可以将第一个连续日期连接到数组的末尾,这样当我们运行算法对它们进行分组时,会自动处理包装。

let names = 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(',');
let i = 0;
while (days[i]+1 == days[i+1]) i++;
days = days.concat(days.splice(0, i+1));
let res = [];
let s = days[0];
for (i = 0; i < days.length-1; i++){
    if ((days[i]+1)%7 != days[i+1]){
        let f = days[i];
        res.push(s == f ? names[s] : names[s]+'-'+names[f]);
        s = days[i+1];
    }
}
f = days[days.length-1];
res.push(s == f ? names[s] : names[s]+'-'+names[f]);
res.unshift(res.pop());