#python #dictionary #join #split #re
Вопрос:
Итак, что я хочу сделать, это преобразовать некоторые слова из строки в соответствующие им слова в словаре и оставить все как есть.Например, введя ввод в виде:
standarisationn("well-2-34 2 @$#beach bend com")
Я хочу выводить как:
"well-2-34 2 @$#bch bnd com"
Коды, которые я использовал, это:
def standarisationn(addr):
a=re.sub(',', ' ', addr)
lookp_dict = {"allee":"ale","alley":"ale","ally":"ale","aly":"ale",
"arcade":"arc",
"apartment":"apt","aprtmnt":"apt","aptmnt":"apt",
"av":"ave","aven":"ave","avenu":"ave","avenue":"ave","avn":"ave","avnue":"ave",
"beach":"bch",
"bend":"bnd",
"blfs":"blf","bluf":"blf","bluff":"blf","bluffs":"blf",
"boul":"blvd","boulevard":"blvd","boulv":"blvd",
"bottm":"bot","bottom":"bot",
"branch":"br","brnch":"br",
"brdge":"brg","bridge":"brg",
"bypa":"byp","bypas":"byp","bypass":"byp","byps":"byp",
"camp":"cmp",
"canyn":"cny","canyon":"cny","cnyn":"cny",
"southwest":"sw" ,"northwest":"nw"}
temp=re.findall(r"[A-Za-z0-9] |S", a)
print(temp)
res = []
for wrd in temp:
res.append(lookp_dict.get(wrd,wrd))
res = ' '.join(res)
return str(res)
но это дает неправильный результат, поскольку:
'well - 2 - 34 2 @ $ % 23beach bnd com'
то есть со слишком большим количеством пробелов и даже без преобразования «beach» в «bch».Итак, в этом проблема.Я подумал, что сначала слишком разделите строку пробелами, а затем разделите результирующие элементы специальными символами и числами и используйте словарь, а затем сначала соедините разделенные строки специальными символами без пробела, а затем весь список пробелом.Кто-нибудь может подсказать, как поступить с этим или каким-нибудь лучшим методом?
Ответ №1:
Вы можете создать регулярное выражение с помощью ключей вашего словаря, гарантируя, что они не заключены в другое слово (т. Е. Не предшествуют и не сопровождаются буквой):
import re
def standarisationn(addr):
addr = re.sub(r'(,|s )', " ", addr)
lookp_dict = {"allee":"ale","alley":"ale","ally":"ale","aly":"ale",
"arcade":"arc",
"apartment":"apt","aprtmnt":"apt","aptmnt":"apt",
"av":"ave","aven":"ave","avenu":"ave","avenue":"ave","avn":"ave","avnue":"ave",
"beach":"bch",
"bend":"bnd",
"blfs":"blf","bluf":"blf","bluff":"blf","bluffs":"blf",
"boul":"blvd","boulevard":"blvd","boulv":"blvd",
"bottm":"bot","bottom":"bot",
"branch":"br","brnch":"br",
"brdge":"brg","bridge":"brg",
"bypa":"byp","bypas":"byp","bypass":"byp","byps":"byp",
"camp":"cmp",
"canyn":"cny","canyon":"cny","cnyn":"cny",
"southwest":"sw" ,"northwest":"nw"}
for wrd in lookp_dict:
addr = re.sub(rf'(?:^|(?<=[^a-zA-Z])){wrd}(?=[^a-zA-Z]|$)', lookp_dict[wrd], addr)
return addr
print(standarisationn("well-2-34 2 @$#beach bend com"))
Выражение состоит из трех частей:
^
соответствует началу строки(?<=[^a-zA-Z])
является lookbehind (т.Е. Не фиксирующим выражением), проверяя, что предыдущий символ является буквой{wrd}
это ключ к вашему словарю(?=[^a-zA-Z]|$)
является промежуточным (т.Е. Не фиксирующим выражение), проверяя, что следующий символ является буквой или концом строки
Вывод:
well-2-34 2 @$#bch bnd com
Редактировать: вы можете скомпилировать целое выражение и использовать re.sub только один раз, если вы замените цикл на:
repl_pattern = re.compile(rf"(?:^|(?<=[^a-zA-Z]))({'|'.join(lookp_dict.keys())})(?=([^a-zA-Z]|$))")
addr = re.sub(repl_pattern, lambda x: lookp_dict[x.group(1)], addr)
Это должно быть намного быстрее, если ваш словарь растет, потому что мы создаем одно выражение со всеми вашими ключами словаря:
({'|'.join(lookp_dict.keys())})
интерпретируется как(allee|alley|...
- функция lambda в re.sub заменяет соответствующий элемент соответствующим значением в lookp_dict (см., Например, Эту ссылку для получения более подробной информации об этом)
Комментарии:
1. Привет, с этим есть проблема. Предположим, у нас есть ввод типа: standarisationn(«well-2-34 2apartment alleyyenence @$% 23beach bend com»), он также преобразует alleyyance в aleyance, то есть преобразует ‘alley’, чего не должно быть, потому что alleyance — это совершенно другое слово. В принципе, это должно быть трудное сопоставление. Спасибо.
2. Хорошо, я понял! Проверьте мой обновленный ответ! это больше похоже на то, что вы ищете?
3. Я думаю, что это решает проблему. Спасибо. Пожалуйста, поделитесь любой ссылкой на регулярное выражение, если у вас есть, которая могла бы помочь лучше понять код.
4. Я обновил свой ответ пояснениями и ссылкой, посвященной лямбде в re.sub. Надеюсь, все это имеет смысл!
5. ты прав! вы должны активно проверять, находится ли ваша совпадающая строка в начале или в конце строки… Я соответствующим образом обновил свой ответ