今天看到一個題,是利用正則找重復最多的字符
let str = 'asss23sjdssskssa7lsssdkjsssdss'
const arr = str.split(/\s*/) // 把字符串轉換為數組
const str2 = arr.sort().join('') // 首先進行排序,這樣結果會把相同的字符放在一起,然后再轉換為字符串
let value = '' let index = 0 str2.replace(/(\w)\1*/g, function($0, $1) { // 匹配字符
if (index < $0.length) { index = $0.length // index是出現次數
value = $1 // value是對應字符
} }) console.log(`最多的字符: ${value} ,重復的次數: ${index}`) // s 17
主要是中間一段正則比較感興趣,涉及到 \1,\2的理解
單獨斜杠的 \1 , \2 表示的是反向引用:
‘\1’ 匹配的是 所獲取的第1個()匹配的引用。例如,’(\d)\1’ 匹配兩個連續數字字符。如33aa 中的33
‘\2’ 匹配的是 所獲取的第2個()匹配的引用。例如,’(\d)(a)\1’ 匹配第一是數字第二是字符a,第三\1必須匹配第一個一樣的數字重復一次,也就是被引用一次。如9a9 被匹配,但9a8不會被匹配,因為第三位的\1必須是9才可以,‘(\d)(a)\2’ 匹配第一個是一個數字,第二個是a,第三個\2必須是第二組()中匹配一樣的,如,8aa被匹配,但8ab,7a7不會被匹配,第三位必須是第二組字符的復制版,也是就引用第二組正則的匹配內容。
這樣其實很明顯了,規則就是:在 \2 的這個位置引用同第2個分組的一模一樣的東西
所以上面的正則就很好理解了:/(\w)\1*/g
(\w):()分組,\w 匹配數字字母下划線
\1:引用該分組的內容
*:匹配前面的子表達式零次或多次。zo* 能匹配 "z" 以及 "zoo"。* 等價於{0,}。
所以上面的函數就很好理解啦。
上面是使用replace方法得到的結果,
stringObject.replace(regexp/substr,replacement)
字符串 stringObject 的 replace() 方法執行的是查找並替換的操作。它將在 stringObject 中查找與 regexp 相匹配的子字符串,然后用 replacement 來替換這些子串。如果 regexp 具有全局標志 g,那么 replace() 方法將替換所有匹配的子串。否則,它只替換第一個匹配子串。
replacement 可以是字符串,也可以是函數。如果它是字符串,那么每個匹配都將由字符串替換。但是 replacement 中的 $ 字符具有特定的含義。如下表所示,它說明從模式匹配得到的字符串將用於替換。
注意:ECMAScript v3 規定,replace() 方法的參數 replacement 可以是函數而不是字符串。在這種情況下,每個匹配都調用該函數,它返回的字符串將作為替換文本使用。該函數的第一個參數是匹配模式的字符串。接下來的參數是與模式中的子表達式匹配的字符串,可以有 0 個或多個這樣的參數。接下來的參數是一個整數,聲明了匹配在 stringObject 中出現的位置。最后一個參數是 stringObject 本身。
其實再利用一次sort()也可以實現需求,如下
function sortNumber(a,b){ return b.length - a.length } let str = 'asss23sjdssskssa7lsssdkjsssdss'
const arr = str.split(/\s*/) // 把字符串轉換為數組
const str2 = arr.sort().join('') // 首先進行排序,這樣結果會把相同的字符放在一起,然后再轉換為字符串
let ans = str2.match(/(\w)\1*/g) ans.sort(sortNumber) ans // ["sssssssssssssssss", "ddd", "aa", "jj", "kk", "2", "3", "7", "l"]
再利用sort()排序,就可以拿到最多的字符