天天看點

從一道JavaScript題目學點正則

這是一篇普通的教程,同時也是我的一篇筆記。起因是看到一道題目的另外一種解法特别有意思,同時也做一點正則的筆記,好了解。

題目

我印象中的這道題目是:

有一組數組為

[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的正則比對

繼續閱讀