几个相似的正则表达式。是否有更快的方法?

2024-10-02 22:37:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一套相当简单的要求。我有一个对象列表(长度200万),每个对象都有两个需要regexed的属性(其他属性不变)

零一二的值。。。需要将10更改为它们的数值:12。。。10个

示例:

ONE MAIN STREET -> 1 MAIN STREET
BONE ROAD -> BONE ROAD
BUILDING TWO, THREE MAIN ROAD -> BUILDING 2, 3 MAIN ROAD
ELEVEN MAIN ST -> ELEVEN MAIN STREET
ONE HUNDRED FUNTOWN -> 1 HUNDRED FUNTOWN

很明显,有些数字是不变的,有些数字收费很奇怪。这完全是意料之中的

我可以把它都用在我下面的东西上。我的问题是,有没有一个聪明的方法让这一切运行得更快?我曾想过制作一个listdictionaries,其中键是单词数字,值是数字,但我认为这对性能没有帮助。或者re.compile每个regex并将它们传递给这个函数?有什么好主意能让它跑得更快吗?你知道吗

def update_word_to_numeric(entrylist):
    updated_entrylist = []
    for theentry in entrylist:
        theentry.addr_ln_1 = re.sub(r"\bZERO\b", "0", theentry.addr_ln_1)
        theentry.addr_ln_1 = re.sub(r"\bONE\b", "1", theentry.addr_ln_1)
        theentry.addr_ln_1 = re.sub(r"\bTWO\b", "2", theentry.addr_ln_1)
        theentry.addr_ln_1 = re.sub(r"\bTHREE\b", "3", theentry.addr_ln_1)
        theentry.addr_ln_1 = re.sub(r"\bFOUR\b", "4", theentry.addr_ln_1)
        theentry.addr_ln_1 = re.sub(r"\bFIVE\b", "5", theentry.addr_ln_1)
        theentry.addr_ln_1 = re.sub(r"\bSIX\b", "6", theentry.addr_ln_1)
        theentry.addr_ln_1 = re.sub(r"\bSEVEN\b", "7", theentry.addr_ln_1)
        theentry.addr_ln_1 = re.sub(r"\bEIGHT\b", "8", theentry.addr_ln_1)
        theentry.addr_ln_1 = re.sub(r"\bNINE\b", "9", theentry.addr_ln_1)
        theentry.addr_ln_1 = re.sub(r"\bTEN\b", "10", theentry.addr_ln_1)

        theentry.addr_ln_2 = re.sub(r"\bZERO\b", "0", theentry.addr_ln_2)
        theentry.addr_ln_2 = re.sub(r"\bONE\b", "1", theentry.addr_ln_2)
        theentry.addr_ln_2 = re.sub(r"\bTWO\b", "2", theentry.addr_ln_2)
        theentry.addr_ln_2 = re.sub(r"\bTHREE\b", "3", theentry.addr_ln_2)
        theentry.addr_ln_2 = re.sub(r"\bFOUR\b", "4", theentry.addr_ln_2)
        theentry.addr_ln_2 = re.sub(r"\bFIVE\b", "5", theentry.addr_ln_2)
        theentry.addr_ln_2 = re.sub(r"\bSIX\b", "6", theentry.addr_ln_2)
        theentry.addr_ln_2 = re.sub(r"\bSEVEN\b", "7", theentry.addr_ln_2)
        theentry.addr_ln_2 = re.sub(r"\bEIGHT\b", "8", theentry.addr_ln_2)
        theentry.addr_ln_2 = re.sub(r"\bNINE\b", "9", theentry.addr_ln_2)
        theentry.addr_ln_2 = re.sub(r"\bTEN\b", "10", theentry.addr_ln_2)
        updated_entrylist.append(theentry)
    return updated_entrylist

也许这只是一个很好的方法。“够好了”的评论对我也很好:)


Tags: 对象restreet属性main数字oneaddr
3条回答
numbers = ["\bZERO\b", "\bONE\b", "\bTWO\b", "\bTHREE\b", "\bFOUR\b", "\bFIVE\b", "\bSIX\b", "\bSEVEN\b", "\bEIGHT\b", "\bNINE\b", "\bTEN\b"]
for theentry in entrylist:
    for i, number in enumerate(numbers):
        theentry.addr_ln_1 = re.sub(r"{}".format(number), "{}".format(i), theentry.addr_ln_1)
        theentry.addr_ln_2 = re.sub(r"{}".format(number), "{}".format(i), theentry.addr_ln_2)

使用一个正则表达式比使用十个要快得多(我注意到速度提高了3倍):

def replace(match):
    return {
        "ZERO": "0",
        "ONE": "1",
        "TWO": "2",
        "THREE": "3",
        "FOUR": "4",
        "FIVE": "5",
        "SIX": "6",
        "SEVEN": "7",
        "EIGHT": "8",
        "NINE": "9",
        "TEN": "10",
    }[match.group(1)]

pattern = re.compile(r"\b(ZERO|ONE|TWO|THREE|FOUR|FIVE|SIX|SEVEN|EIGHT|NINE|TEN)\b")

def update_word_to_numeric(entrylist):
    updated_entrylist = []
    for theentry in entrylist:
        theentry.addr_ln_1 = pattern.sub(replace, theentry.addr_ln_1)
        theentry.addr_ln_2 = pattern.sub(replace, theentry.addr_ln_2)
        updated_entrylist.append(theentry)
    return updated_entrylist

我使用鲜为人知的函数来传递re.sub一个函数作为第二个参数:它将接受一个匹配对象并返回替换字符串。这样我们就可以查到替换字符串了。你知道吗

我还使用了re.compile来预编译regex,这也提高了时间,但没有大的改变那么多。你知道吗

以下是使用字典的方法:

s = '''
ONE MAIN STREET
BONE ROAD
BUILDING TWO, THREE MAIN ROAD
ELEVEN MAIN ST
ONE HUNDRED FUNTOWN
'''

d = {'ZERO':'0', 'ONE':'1', 'TWO':'2', 'THREE':'3', 'FOUR':'4', 
     'FIVE':'5', 'SIX':'6', 'SEVEN':'7', 'EIGHT':'8', 'NINE':'9', 
     'TEN':'10', 'ELEVEN':'11', 'TWELVE':'12'}

p = re.compile(r'\b(' + '|'.join(d.keys()) + r')\b')
r = p.sub(lambda x: d[x.group()], s)

print(r)

根据需要从字典中添加或删除条目。你知道吗

相关问题 更多 >