需求

最近项目有一个字段筛选需要选择连续的月份,它所有的值就是一年的12个月份——1、2、3...12,算连续有两种情况:第一种是年内的,就是不超过12月份;还有一种是跨年的,就是从今年的某个月份到第二年的某个月份,例如:11、12、1、2,这样也算是连续的。

解决步骤

一开始是没有想到要跨年份的,所以很简单,给数组排个序,然后计算前一位减后一位的差是否等于1就行了:

function MonthIsContinuous(arr) {
  const sort_arr = arr.sort((a, b) => a - b);
  return !sort_arr.some((v, i, source) => {
    if((i + 1) < source.length) {
      if((source[i + 1] - v) !== 1) {
        return true
      }else {
        return false
      }
    }else {
      return false
    }
  })
}

后来经过后端确认,第二种情况也算是连续的,于是上面这种方案是行不通的。

然鹅,像11、12、1、2这种数据按月份的话要怎么判断是否是连续的呢?按从小到大排序之后是这样的1、2、11、12,按照上面的方法,是无法得知是从哪个位置开始断开的,并且断开之后是否连续还要有另外计算,把这几个数字写在纸上之后,突然灵机一动,发现只要对比出排序之后的数据和112之间的差集,然后判断差集是否连续不就得了!

// 1、2、11、12
// 差集为3、4、5、6、7、8、9、10
// 差集是连续的,从而推断出原数组是连续的

实现

function numberIsContinuous(arr){
  return !arr.some((v, i, source) => {
    if((i + 1) < source.length) {
      if((source[i + 1] - v) !== 1) {
        return true
      }else {
        return false
      }
    }else {
      return false
    }
  })
}
function MonthIsContinuous(arr) {
  const arr_sort = arr.sort((a, b) => a - b);
  if(arr.indexOf(12) >= 0) {  // 当月份中有12月的时候需要算差集,没有则直接算排序之后数值差
    const month = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
    const diff = month.filter(v => arr_sort.indexOf(v) === -1);
    // ⬇️当月份数组与完整数组想差只有一个月时,说明一定间隔了一个月,所以是不连续的
    return diff.length === 1 ? false : numberIsContinuous(diff);
  }else {
    return numberIsContinuous(arr_sort);
  }
}

算法

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

npm包发布以及删除流程 上一篇
下拉框组件问题梳理 下一篇