连续的数字,则只取第一个和最后一个数字,中间使用~连接,如果是独立的数字则单独返回
let str = "1,2,3,5,8,11"
let s= getStr(str)
s // 1~3,5,8,11
方法1
思路 利用
redcue方法,生成1~2~3,5,8,11,然后通过正则 把1~2~3替换 成1~3
function getStr(str: string) {
const arr = str.split(",").map(Number);
let target = arr.reduce((pre, cur, index, arr) => {
if (index > 0) {
// 说明是连续的 the statement is continuous
if (cur - 1 == arr[index - 1]) {
return `${pre}~${cur}`;
} else {
return `${pre},${cur}`;
}
} else {
// return current Value when index equals 0
return cur;
}
}, "");
// 1~2~3~5~8~11,使用 正则
return target.replace(/(\d{1,})(~\d{1,})*(~\d{1,})/g, "$1$3");
}
let a = getStr("1,2,3,5,8,11");
方法2
思路 通过遍历,判断当前值 与下一个值的关系,只有当他们不相邻的情况下
(item + 1 != arr[index + 1]),进入 if 语句,然后 判断 当前值 是否是 孤独 的(tmp !== item ),当 判断完毕后 ,tmp需要 被复制为 数组的下一项(tmp = arr[index + 1];),等到下次遍历, 如果 tmp 又和当前值相等了,说明他是孤单的
function getStr(str: string) {
const arr = str.split(",").map(Number);
const result = [];
let tmp = arr[0];
arr.forEach((item, index, arr) => {
// 判断 他们不是相邻的
if (item + 1 != arr[index + 1]) {
console.log(tmp);
// tmp 可以看做一个 start 值,如果 start 和 当前值 是一样的话,说明是 单独的一个值
if (tmp !== item) {
result.push(`${tmp}~${item}`);
} else {
result.push(item);
}
// tmp 为当前值的下一个值
tmp = arr[index + 1];
}
});
return result.join();
}
方法3
思路
双指针首先字符串转数组 用 fast 和 slow 遍历数组,有以下几种情况:
- arr【fast】 + 1 == arr【fast + 1】: 说明是连续的,fast 继续往后走即可
- else
- fast != slow: 说明是类似 1, 2, 3, 4 这样的连续字符,push {fast},fast 继续向后遍历,并且移动 slow 到 fast 的位置
- fast == slow: 说明是不连续数字,直接 push slow 即可,fast 和 slow 都向后移动
function getStr(str: string) {
const arr = str.split(",").map(Number);
let slow = 0,
fast = 0,
result = [];
for (let i = 0; i < arr.length; i++) {
if (arr[fast] + 1 == arr[fast + 1]) {
fast++;
} else {
if (fast != slow) {
result.push(`${arr[slow]}-${arr[fast]}`);
slow = fast + 1;
} else {
result.push(`${arr[slow]}`);
slow++;
}
fast++;
}
}
return result;
}
note:思路出自B站 www.bilibili.com/video/BV1uP… ,time:2022,5,25 15:03