2

昨天,女朋友的同事在他们群里讨论一个面试题,题目是这样婶儿的:输入 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

非常感谢 @老鼠拧刀满街找猫,发现了这个解法的问题,谢谢!!!

就是偶数的正则匹配存在问题,当出现 a12a122结果就是错的,所以修改如下:

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_]'

zhangjinpei
103 声望6 粉丝

做一枚精致的前端er