昨天,女友的同事在他們羣裏討論一個面試題,題目是這樣嬸兒的:輸入 get1_install2_app3_list4_by5_android6
, 每一個單詞後面總會攜帶一個數字,只有偶數才刪掉,在不使用循環控制語句,只用正則表達式,實現輸出 get1InstallApp3ListBy5Android
。android
ok, 廢話很少說直接開幹:面試
首先,觀察輸入,發現規律是這樣的 英文
+ 數字
+ _
,而後,不能有偶數因而,天然而然有如下正則:正則表達式
/[a-z]+[13579]+/gi
segmentfault
var str = 'get1_install2_app3_list4_by5_android6'; str.match(/[a-z]+[13579]+/gi) // ["get1", "app3", "by5"]
發現,偶數前的英文掉了,因而,有了下面:數組
/[a-z]+[13579]+_[a-z]+/gi
app
str.match(/[a-z]+[13579]+_[a-z]+/gi); // ["get1_install", "app3_list", "by5_android"]
剩下就是把 _
替換掉,就能夠了code
str.match(/[a-z]+[13579]+_[a-z]+/gi).join('').replace(/_/g,'') // get1installapp3listby5android
貌似,是能夠了,可是,若是three
var str = 'get1_install2_app3_list4_by5_android6_demo7'; str.match(/[a-z]+[13579]+_[a-z]+/gi); // ["get1_install", "app3_list", "by5_android"]
發現 demo7
不見了。negative字符串
上面的正則,在有奇數個 英文
+ 數字
時候,會漏掉最後一個,由於,咱們的正則 是 英文
+ 數字
+ ’英文‘,demo7
是 英文
+ 數字
,因此不匹配。因而,再加上這個不就能夠了嗎,因而有了:get
/[a-z]+[13579]+_[a-z]+|[a-z]+[13579]+/gi
var str = 'get1_install2_app3_list4_by5_android6_demo7'; str.match(/[a-z]+[13579]+_[a-z]+|[a-z]+[13579]+/gi) // ["get1_install", "app3_list", "by5_android", "demo7"]
貌似,是能夠了,可是,若是
str 不是 嚴格的 英文_奇數_英文_偶數_...
這樣的規律,而是 英文_偶數_英文_奇數...
,就不行了,好比:
var str = 'get0_install1_app2_list3_by4_android5_demo6'; str.match(/[a-z]+[13579]+_[a-z]+|[a-z]+[13579]+/gi) // ["install1_app", "list3_by", "android5_demo"]
發現 get
不見了。negative
發現,思路錯了,既然要求是須要刪掉 偶數
,爲啥不從 偶數
出發,匹配 非偶數
/[^02468]+/gi
var str = 'get0_install1_app2_list3_by4_android5_demo6'; str.match(/[^02468]+/gi); // ["get", "_install1_app", "_list3_by", "_android5_demo"]
貌似,是能夠了,可是,仔細觀察輸出,
發現,人家還有 小駝峯命名, negative
上一步中,已經 獲得 相似這樣的數組:["get", "_install1_app", "_list3_by", "_android5_demo"]
只需將 _字符
替換爲 大寫,便可:
var str = 'get0_install1_app2_list3_by4_android5_demo6'; str.match(/[^02468]+/gi).join('').replace(/_\w/g, function(word) { return word.substring(1).toUpperCase(); }); // getInstall1AppList3ByAndroid5Demo
歐耶,終於,符合要求了 victory。
這個解法有問題 round six 有解釋
如今回過頭想一想,發現,根本不須要那麼多過程。從一開始的思路錯誤,到後來的思路調整,最後,得出答案,可是,若是,咱們換一種思路,從新思考這道題:
輸入:get1_install2_app3_list4_by5_android6
輸出:get1InstallApp3ListBy5Android
特色:偶數去掉了;小駝峯命名;
因而 有了:
var str = "get1_install2_app3_list4_by5_android6"; str.replace(/[02468]+/g, '').replace(/_\w/g, function(word) { return word.substring(1).toUpperCase(); });
因此,要善於審題(0_0),找出最核心要求,Give me five
這個解法有問題 round six 有解釋
很是感謝 @老鼠擰刀滿街找貓,發現了這個解法的問題,謝謝!!!
就是偶數的正則匹配存在問題,當出現 a12
、a122
結果就是錯的,因此修改以下:
var str = "one1_two2_three3_four4_five5_six6_seven7_eight8_nine9_ten10_eleven11_twelve12_a123_b122_c1223"; str .replace(/\d+/g, function(num) { return num % 2 ? num : ''; }) .replace(/_\w/g, function(word) { return word.substring(1).toUpperCase(); }); // one1TwoThree3FourFive5SixSeven7EightNine9TenEleven11TwelveA123BC1223
但願此次沒啥大問題,尷尬0_0!
答案是什麼,已經特別重要,重要的是思想的過程。記錄下,我是怎麼一步一步試錯知足要求的。若是你有更好的解法,歡迎評論去留言。
最後,列下用到了正則的哪些知識點。
[abc]
查找方括號之間的任何字符[a-z]
查找任何從 a 至 z 的字符n+
匹配任何包含至少一個 n 的字符串[^xyz]
不匹配這個集合中的任何一個字符\w
匹配字母或數字或下劃線或漢字 等價於 '[^A-Za-z0-9_]'