leetcode上有一道很简单的题目:
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,忽略字母的大小写。
将题目拆解成两部分:
第一,处理字符串,使其只保留字母和数字,且字母统一大小写;
第二,验证回文串。
本文先来讲讲第一部分。
改变字母大小写很简单,用内置函数即可。重点在于只保留字母和数字字符。
我首先想到的是正则。对于正则,我并不是很会。难者不会,会者不难,我觉得它太难了,完全不适合我这种又懒又笨的猪脑子,向来是现用现查。这一查,就查出两种方法。
算上不用正则的,总计3种方案,且听我一一道来。
re.sub(pattern, repl, string, count = 0, flags = 0)
这个函数一般只需要掌握前三个参数:
pattern,正则中的模式字符串。
repl,希望被替换成的字符串。
string,要被处理的原始字符串。
返回处理过的字符串。
如果完全不懂正则表达式,pattern还是挺难理解的。在以后的知识分享系列里,我会写一写关于正则表达式的内容。
举个例子:
re.sub("[a-zA-Z0-9]", "", mystr) # 把字符串中的字母和数字都弄没
第一个参数,模式字符串,表示所有的字母和数字;
第二个参数,希望被替换成的字符串,是个空字符串;
第三个参数,希望被处理的原始字符串,变量名为mystr;
返回处理过的字符串。
那么替换的逻辑就很好理解了。想只保留某种字符,就把除了该类字符以外的所有字符都替换成空字符串。
但这样有点不方便。如果只想保留中文,那么为了替换掉其他所有字符,就要在模式字符串里把其他所有类型的字符,包括字母、数字、特殊字符等等,全面地枚举一遍,写不全的话就会有漏网之鱼。
于是咱们改进一下做法:
re.sub("[^a-z^A-Z^0-9]", "", mystr) # 只保留字母和数字,其他的都弄没
把除了字母和数字以外的东西都弄没。我可真是个小机灵鬼!
所以,如果想只保留中文,就可以这样写:
re.sub("[^\u4e00-\u9fa5]", "", mystr) # 只保留汉字,其他的都弄没
这种思路就比较直截了当。
re.findall(pattern, string, flags = 0)
这个函数一般只需要掌握前两个参数:
pattern,正则中的模式字符串。
string,要被处理的原始字符串。
返回所有与模式相匹配的字符的列表。
re.findall("[a-z]",mystr) # 返回字符串中所有小写字母的列表
得到列表之后,再来一个把序列连接成字符串的join方法,大功告成!
''.join(re.findall("[a-z]",mystr)) # 只保留小写字母,其他的都弄没
如果用正则,sub替换和findall查找这两种方法均可,用哪个就看个人喜好。
然而,做leetcode算法题,一般来说是用不着调用库的。
官方标答是如何做到只保留字母和数字的呢?请看:
sgood = "".join(ch.lower() for ch in s if ch.isalnum())
也就是第三种方法:
什么叫专业啊?一般人,看什么都觉得似曾相识,但是到了实际要用的时候就两眼一抹黑,什么都想不起来,比如我。而那些真正融会贯通、运用自如的人,才叫真的专业。
一开始看到python字符串拥有一堆诸如isalnum(), isalpha(), isdigit(), islower(), isupper()函数的时候,我还不以为意,想不到竟有如此妙用!
令我稍感欣慰的是,经过测试,这个方法比用正则的运行速度慢。看来正则还是有其用武之地的!
只保留字符串的特定字符,你学会了吗?
下期预告:验证回文串
参考资料:
https://leetcode-cn.com/problems/valid-palindrome/solution/yan-zheng-hui-wen-chuan-by-leetcode-solution/
https://docs.python.org/2/library/re.html
https://www.runoob.com/python3/python3-string.html