这是一篇普通的教程,同时也是我的一篇笔记。起因是看到一道题目的另外一种解法特别有意思,同时也做一点正则的笔记,好理解。
题目
我印象中的这道题目是:
有一组数组为[1,1,2,3,3,3,3,4,5,5,5,6,6]
使用js
把它变成[[1,1],2,[3,3,3],4,[5,5,5].[6,6]]
解法有很多,我这里只列出两种
解法一
我们平时的解法一般为:
数组嵌套,将含有相同的值得数组放入新数组里面
然后对新数组进行,对里面的嵌套数组进行个数判断并返回值,重新组成一个新数组
新数组就是答案
var arr = [1,1,2,3,3,3,3,4,5,5,5,6,6];
var tempArr = [];
var result = [];
var i,len,item,lastArr;
for(i = 0,len = arr.length;i < len;i++){
item = arr[i];
lastArr = tempArr.slice(-1)[0];
if(!lastArr || lastArr[0] != item){
lastArr = [];
tempArr.push(lastArr);
}
lastArr.push(item);
}
for(i=0,len=tempArr.length;i<len;i++){
item = tempArr[i];
result.push(item.length > 1 ? item : item[0]);
}
console.log(result);
解法二
如果我们用正则的话,那解法如下:
var arr = [1,1,2,3,3,3,3,4,5,5,5,6,6];
var result = "[" +
(arr.toString() + ",")
.replace(/(([^,]+,)\2+)/g,'[$1],')
.replace(/,(]|$)/g,'$1')
+ "]";
console.log(JSON.parse(result));
这样一下子就变得很高效,正则找出两个以上的相同值的位置,插入[]
然后打印出来即可。
从这段代码,我们可以看出,
先对把数组字符串化
var result = "[" +
(arr.toString() + ",")
+ "]";
变成[1,1,2,3,3,3,3,4,5,5,5,6,6,]
然后匹配两个以互为相同的值,套上[]
var result = "[" +
(arr.toString() + ",")
.replace(/(([^,]+,)\2+)/g,'[$1],')
+ "]";
最后是找到]
前面多余的,
var result = "[" +
(arr.toString() + ",")
.replace(/(([^,]+,)\2+)/g,'[$1],')
.replace(/,(]|$)/g,'$1')
+ "]";
JSON.parse(result)
转为数组对象,打印即可
正则表达式
通过解法二,我们有时候面对一些问题,其实还有更简单的解决方法
下面再补充一下正则的知识点
元字符
从.replace(/((\[^,]+,)\2+)/g,'[$1],')
中,正则部分是/((\[^,]+,)\2+)/g
其中最前面的“/”与最后面的“/”是分隔符,表示正则表达式的开始与结束.
这里再补充元字符的说明
代码 | 含义 |
---|---|
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母或数字或下划线或汉字 |
\W | 匹配任意不是字母或数字或下划线或汉字的字符 |
\s | 匹配任意的空白符 |
\S | 匹配任意非空白符 |
\d | 匹配数字 |
\D | 匹配非数字 |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
标志
最后的“g”标志表示正则表达式使用的global(全局)的状态.使用 global 标志表明在被查找的字符串中搜索操作将查找所有符合的项,而不仅仅是第一个.这也被称为全局匹配.【相关的标志还有i(ignoreCase,表示忽略大小写)、m(multiline,表示允许跨行)】,如下表所示
补充一下标志
标志 | 描述 |
---|---|
g | 全局搜索 |
i | 不区分大小写搜索 |
m | 多行搜索 |
y | 执行“粘性”搜索,匹配从目标字符串的当前位置开始,可以使用y标志 |
限定符
然后我们再来看中间的主体部分((\[^,]+,)\2+)
字符组就是在[]
(方括号)中列举出所有的可能再去匹配,+
是指匹配前面一个表达式1次或者多次,
补充一下限定符
代码 | 含义 |
---|---|
* | 复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
.replace(/((\[^,]+,)\2+)/g,'[$1],')
中的$1
匹配到的部分的替换,替换成[$1]
,
匹配的部分,值得是两个以上相同的值
.replace(/,(]|$)/g,'$1')
就是去,]
里的,
写得好乱···
我这篇文章也用到了对URL的正则匹配
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。