面试题答案
一键面试- 编译正则表达式:
import re
date_pattern = re.compile(r"""(?x)
(?:
(\d{4}) - (\d{2}) - (\d{2}) |
(\d{2}) / (\d{2}) / (\d{4}) |
(January|February|March|April|May|June|July|August|September|October|November|December) (\d{2}), (\d{4})
)
""")
解释:
- re.compile
函数将正则表达式编译成一个正则对象,提高匹配效率。
- (?x)
是一个标志,表示开启详细模式,这样正则表达式中的空白字符(除了在字符类中或转义序列中的)会被忽略,并且可以使用 #
进行注释,使正则表达式更易读。
- (?:...)
是一个非捕获组,它用于对模式进行分组,但不捕获匹配的文本。
- (\d{4}) - (\d{2}) - (\d{2})
匹配 YYYY - MM - DD
格式。
- (\d{2}) / (\d{2}) / (\d{4})
匹配 MM/DD/YYYY
格式。
- (January|February|March|April|May|June|July|August|September|October|November|December) (\d{2}), (\d{4})
匹配 Month DD, YYYY
格式。
- 性能优化:
- 预编译正则表达式:如上述代码,使用
re.compile
预编译正则表达式,避免每次匹配时都进行编译,这在大量数据匹配场景下能显著提高性能。 - 减少捕获组:仅在需要提取日期各部分时使用捕获组。在不需要提取时,尽量使用非捕获组
(?:...)
代替捕获组(...)
,因为捕获组会增加处理开销。 - 使用
re.finditer
而非re.findall
:如果只需要迭代匹配结果而不需要获取整个匹配列表,re.finditer
更高效,因为它是惰性的,每次只返回一个匹配对象,而re.findall
会返回所有匹配结果的列表,占用更多内存。 - 避免不必要的回溯:确保正则表达式尽可能具体和明确,减少不必要的可选分支和重复模式,因为回溯会增加匹配时间。例如,对于月份的匹配,如果数据来源确定月份只会是完整英文拼写,就不要添加其他可能的匹配方式(如缩写)。
- 分块处理数据:对于海量文本数据,不要一次性处理整个数据集,而是分块读取和匹配,这样可以减少内存占用,同时也可能提高匹配效率。
- 预编译正则表达式:如上述代码,使用