Для чистого решения регулярных выражений - я бы сделал:
import re
sample_=["John Doe", "J.K.Rowling", "Marie Anne Richardson", "John D O E", "John Doe Doe"]
res=""
for el in sample_:
print(f"BEFORE: {el}")
res=re.sub(r"[^a-z\s]", "", el.lower().strip())
res=re.sub(r"(?<=\s)([^\s]*)\s", r"\1", res)
res=re.sub(r"(^[a-z]{1,2}).{0,}?([a-z]{1,6})$", r"\1\2", res)
print(f"AFTER: {res}")
Выходы:
BEFORE: John Doe
AFTER: jodoe
BEFORE: J.K.Rowling
AFTER: jkowling
BEFORE: Marie Anne Richardson
AFTER: maardson
BEFORE: John D O E
AFTER: jodoe
BEFORE: John Doe Doe
AFTER: jodoedoe
Что там происходит:
Первые 2 re.sub(...)
просто избавиться от всех небуквенных символов, кроме первого пробела внутри строки (так что вы можете точно различать guish какое первое слово в имени - получить первые 1-2 символа).
Второй: "(^[a-z]{1,2}).{0,}?([a-z]{1,6})$"
pull:
(1) (группа 1 - из-за квадратных скобок) (^[a-z]{1,2})
соответствует первым двум буквам строки, тогда как это жадный оператор, поэтому он будет соответствовать всем 2, если есть внутренняя часть 2.
(2): .{0,}?
соответствует любому количеству символов, хотя и не является жадным (вот что указывает вопросительный знак) - следовательно, он будет совпадать с небольшим насколько это возможно.
(3) (группа 2 - из-за квадратных скобок) ([a-z]{1,6})$
будет соответствовать до 6 последним символам в конце, тогда как снова это жадный оператор, следовательно, он будет соответствовать максимально возможному .
Вся строка соответствует тому, что мы заменили на группу 1 и группу 2 (h Кроме того, мы опускаем внутреннюю часть).
Некоторые ссылки на python регулярное выражение lib: re
:
https://docs.python.org/3.5/library/re.html