需求
最近项目有一个字段筛选需要选择连续的月份,它所有的值就是一年的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
,按照上面的方法,是无法得知是从哪个位置开始断开的,并且断开之后是否连续还要有另外计算,把这几个数字写在纸上之后,突然灵机一动,发现只要对比出排序之后的数据和1
到12
之间的差集,然后判断差集是否连续不就得了!
// 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);
}
}