Несколько похожих регулярных выражений.Более быстрый способ сделать это? - PullRequest
0 голосов
/ 24 мая 2018

У меня довольно простой набор требований.У меня есть список (длиной 2 миллиона) объектов, каждый из которых имеет 2 свойства, которые необходимо переопределить (другие свойства не изменяются)

Значения ZERO ONE TWO ... TEN необходимо изменить на ихчисловое значение: 1 2 ... 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

Ясно, что некоторые числа не меняются, а некоторые взимаются странным образом. что вполне ожидаемо

Я могу заставить все это работать с тем, что у меня есть ниже.У меня вопрос, есть ли умный способ заставить все это работать быстрее?Я думал о создании list из dictionaries, где ключи - это числа слов, а значения - числовые, но я не думаю, что это поможет с производительностью.Или re.compile каждое регулярное выражение и передать их в эту функцию?Есть какая-нибудь умная идея, чтобы сделать это быстрее?

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

Может быть, это просто прекрасный способ сделать это.Комментарии "это достаточно хорошо" тоже хорошо со мной:)

Ответы [ 3 ]

0 голосов
/ 24 мая 2018
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)
0 голосов
/ 24 мая 2018

Вот подход с использованием словаря:

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)

Добавить или удалить записи из словаря по своему усмотрению.

0 голосов
/ 24 мая 2018

Гораздо быстрее использовать одно регулярное выражение вместо десяти (я заметил увеличение скорости в 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 для предварительной компиляции регулярного выражения, это также улучшило время, но не так сильно, как большое изменение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...