测试数据类型时,在for循环中使用正则表达式的最佳方法是什么?

时间:2019-05-28 19:01:35

标签: python regex performance

在测试数据类型时,在for循环中使用正则表达式的最佳方法是什么?

对于上下文,我正在遍历具有多种数据类型的大型不干净数据集,并且需要查找字符串扩展名(如果存在)。对我的代码进行少量更改(例如将值转换为字符串)会花费我几分钟的时间。

我通读了这个问题Python: How to use RegEx in an if statement?,但没有找到一种方法来测试是否匹配,而没有先转换为字符串。

值:

vals = [444444, '555555-Z01']
pattern = re.compile('[-]*[A-Z]{1}[0-9]{2}$')
# new_vals = [444444, 555555]

慢速方法: (每个循环2.4 µs±93.6 ns)

new_vals = []
for v in vals:
    if type(v)==str:
        if pattern.search(v) is not None:
            new_v = pattern.findall(v)[0].replace('-','')
            new_vals.append(new_v)
    else:
        new_vals.append(v)

快速方法: (每个循环1.84 µs±34.7 ns)

f = lambda x: x if type(x)!=str else pattern.findall(x)[0].replace('-','')

new_vals = []
for v in vals:
    new_vals.append(f(v))

方法失败:

new_vals = []
for v in vals:
    if ((type(v)==str) & (pattern.search(v) is not None)):
        new_vals.append(v)

错误:

TypeError: expected string or bytes-like object

1 个答案:

答案 0 :(得分:1)

我尝试使用try/except块来击败您的尝试,但是异常处理似乎花费了太多时间。 “要宽恕多于允许”要这么多……

如果仅将&换成and,则最后一次尝试是最有前途的,因为&是合乎逻辑的并且不会短路。

为此,我将在列表理解中加快速度,并放弃is not None测试,这是无用的,因为如果search成功,它将返回一个正则表达式对象,即诚实:

new_vals = [v for v in vals if type(v)==str and pattern.search(v)]

或使用isinstance(同样的速度,也测试str的子类):

new_vals = [v for v in vals if isinstance(v,str) and pattern.search(v)]