Как разделить символы строки пробелами, а затем результирующие элементы списка специальными символами и цифрами, а затем снова соединить их?

#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. ты прав! вы должны активно проверять, находится ли ваша совпадающая строка в начале или в конце строки… Я соответствующим образом обновил свой ответ