昨天,女朋友的同事在他们群里讨论一个面试题,题目是这样婶儿的:输入 get1_install2_app3_list4_by5_android6
, 每个单词后面总会携带一个数字,只有偶数才删掉,在不使用循环控制语句,只用正则表达式,实现输出 get1InstallApp3ListBy5Android
。
ok, 废话不多说直接开干:
round one
首先,观察输入,发现规律是这样的 英文
+ 数字
+ _
,然后,不能有偶数于是,自然而然有以下正则:
/[a-z]+[13579]+/gi
var str = 'get1_install2_app3_list4_by5_android6';
str.match(/[a-z]+[13579]+/gi)
// ["get1", "app3", "by5"]
发现,偶数前的英文掉了,于是,有了下面:
/[a-z]+[13579]+_[a-z]+/gi
str.match(/[a-z]+[13579]+_[a-z]+/gi);
// ["get1_install", "app3_list", "by5_android"]
剩下就是把 _
替换掉,就可以了
str.match(/[a-z]+[13579]+_[a-z]+/gi).join('').replace(/_/g,'')
// get1installapp3listby5android
貌似,是可以了,但是,如果
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
round two
上面的正则,在有奇数个 英文
+ 数字
时候,会漏掉最后一个,因为,我们的正则 是 英文
+ 数字
+ ’英文‘,demo7
是 英文
+ 数字
,所以不匹配。于是,再加上这个不就可以了吗,于是有了:
/[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
round three
发现,思路错了,既然要求是需要删掉 偶数
,为啥不从 偶数
出发,匹配 非偶数
/[^02468]+/gi
var str = 'get0_install1_app2_list3_by4_android5_demo6';
str.match(/[^02468]+/gi);
// ["get", "_install1_app", "_list3_by", "_android5_demo"]
貌似,是可以了,但是,仔细观察输出,
发现,人家还有 小驼峰命名, negative
round four
上一步中,已经 得到 类似这样的数组:["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 有解释
round five
现在回过头想想,发现,根本不需要那么多过程。从一开始的思路错误,到后来的思路调整,最后,得出答案,但是,如果,我们换一种思路,重新思考这道题:
输入: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 有解释
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_]'
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。