正規表示式
完成乙個函式isusdformat
返回true
/false
來判斷乙個字串是否符合美元格式:
以$
開頭
如果是小數,保留兩位小數;如果不是小數則不顯示小數部分
整數部分從小數點上一位開始每隔三位用,
分割開來
如果整數部分從數字0
開始,則只會顯示一位0
例如:
isusdformat('$1') // => true
isusdformat('$1.0') // => false
isusdformat('$100,000.00') // => true
isusdformat('$0,000.00') // => false
isusdformat('$0.00') // => true
isusdformat('$11,23,345.33') // => false
isusdformat('$1,123,345.33') // => true
這道題目和之前在面試中遇到過的為數字新增逗號的問題有一點點類似,先來看這道題目。
正規表示式是非常強大的,如果不用正規表示式,需要在函式裡面進行拆分判斷,所以還是需要多練習正則的使用
這道題,我又沒有做出來,還是水平太低,看了討論區的答案,好好分解一下:
實現,要判斷的格式分為三個部分,就是$
加上整數部分再加上(肯能存在的)小數部分:
/^$(整數部分)(小數部分)?$/
先看比較容易的小數部分,小數部分如果存在時,構成就是小數點加上兩位數字,所以:
// 小數部分
/\.\d/
再來看整數部分,整數部分大體上可分為兩種情況,情況1是以0開始,情況2就是不以0開始,那麼兩種情況可以用|
來分割,兩種情況都是滿足要求的:
// 整數部分
((情況2)|0)
再來看情況2,它有兩個要求,首位不能是0
,並且從末尾(單詞結束或者小數點位置)起每三位用,
分割,所以情況2為:
/[1-9]\d(,\d)*/
上面表達的意思就是第一位是非0
的整數,然後接著的數字可能是0,1,2三種,也就是說三面這一半匹配了x
/xx
/***
三種形式的數字,後面如果再有數字的話就是後面括號中的內容,必須接著乙個逗號和三位數字,當然這部分也可以沒有,所以用*
來限制數量
所以拼接到一起就是:
const isusdformat = str => /^\$([1-9]\d(,\d)*|0)(\.\d)?$/.test(str)
說說拿到面試題,很簡單,就是使用正則為乙個數字,從右向左每三位新增乙個,
這道題目我當時沒有用直接用正則做出來,因為我覺得正則是從左至右進行判斷,而現在是從右至左新增,所以不知道怎麼搞。
我當時的做法就是將字串反轉後進行新增,新增完了再反轉回去。
如果不採用這種形式怎麼實現呢?
首先要了解一下在正則中的先行斷言
先行斷言是是用來判斷位置的,比如x(?=y)
,代表的是如果x
後面跟的是y
,那麼就匹配x
,在xyz
中,匹配結果就是x
,不包括y
,因為y
是作為先行斷言進行判斷位置的。
與先行斷言對應的就是後行斷言(?!
),比如x(?!y)
表示後面不是y
才會匹配x
,所以xyz
中的x
就不會被匹配,而xzy
中的x
會被匹配
然後再來看一下我們要用到的\b
和\b
,它們是用來匹配位置的(注意是匹配,而不是判斷),\b
匹配的是單詞邊界,而\b
正好相反,也就是匹配非單詞邊界的位置
我的理解是,比如123
,\b
匹配是1
之前和3
之後的位置,\b
匹配的是1
和2
以及2
和3
之間的位置
1 2 3
| | | |
| | | |
\b \b \b \b
那麼如果用replace
方法對\b
和\b
的匹配進行替換是什麼效果呢?
let a = '123'.replace(/\b/g, '!')
a // "!123!"
實現了新增的效果,因為被我們替換掉的是乙個位置,而非乙個字元。這就是我們能夠使用replace
實現需求的原因。
然後來看具體的正規表示式,以12345
舉例
我們首先要明確,要匹配的就是乙個位置,這個位置將被替換為,
,這個位置的特殊性是它後面應該跟著3個數字
到目前位置我們的正規表示式就是:
/\b(?=(\d))/
上面,\b
匹配非單詞邊界,匹配的結果將是12
/23
/34
/45
各自數字之間的位置
然後後面通過乙個先行斷言對\b
進行了約束,那就是這個位置後面必須跟著3個數字,那現在匹配的結果就是12
/23
之間的位置了,都可以滿足要求
實際上12
之間後面跟著3個數字,3個數字後面又跟著乙個數字,而我們要的不是這樣,它後面需要是單詞的結束(或者說是單詞的邊界),所以需要在後面增加另外的位置判定($
或者\b
)
/\b(?=(\d)\b)/
這樣就能正確12345
,而對於12345123456
,可能有多個符合條件的先行斷言位置要匹配,所以需要增加量詞+
/\b(?=(\d)+\b)/
我之前理解錯了,以為是有多個\b
要匹配,+
應該加在最外層的括號外邊,其實不是,多個\b
要匹配是replace
的g
完成的
所以最後的結果是:
const reformat = str => str.replace(/\b(?=(\d)+\b)/g, ',')
這只是對整數部分的處理,如果有小數部分,我沒想到怎麼直接用正則一次搞定,還是需要先判斷是否有小數,然後將整數部分分割出出來單獨處理,然後再把小數部分拼接上。 程式設計之美 4 9數獨知多少
問題 一共有多少種不同的數獨解答呢?其中有多少種是獨立的解答呢?如果用乙個字串來表示各種數獨,如何保證一一對應的基礎上,讓字串的長度最短?分析 首先要明確問題,獨立的解答到底是什麼?如何定義 獨立 這種關係?如果任意交換數獨的兩個數字,仍然是乙個合法的數獨。那麼我們可以定義 如果兩個數獨解答可以通過...
前端常見判斷
checkbox id prop checked 以後,返回true or false 設定checkbox是否被選中 input name selectit prop checked true false input name selectit prop checked selectit prop...
程式設計之美變形記 「49」的個數
昨天在杭電poj上看到乙個道題。題目總結出來就是,給定乙個正整數n,求出從1到n 包含n 之間49出現的個數。舉例 如n 101 則1到101之間101個數中,49出現一次。同時,409,4009 這樣的數字不合法 看到第一眼就想起來程式設計之美2.4有一道求 1 的個數的題目,這道題其實就是把 1...