Python, видаліть усі не алфавітні символи зі рядка


90

Я пишу програму підрахунку слів MapReduce. Проблема полягає в тому, що в даних є багато символів, не пов’язаних з алфавітом, я знайшов цю публікацію Видалення з рядка в Python всього, крім буквено-цифрових символів, що показує гарне рішення за допомогою регулярного виразу, але я не впевнений, як це реалізувати

def mapfn(k, v):
    print v
    import re, string 
    pattern = re.compile('[\W_]+')
    v = pattern.match(v)
    print v
    for w in v.split():
        yield w, 1

Боюсь, я не впевнений, як користуватися бібліотекою reчи навіть регулярним виразом з цього приводу. Я не впевнений, як правильно застосувати шаблон регулярного виразу до вхідного рядка (рядок книги), vщоб отримати новий рядок без будь-яких буквено-цифрових символів.

Пропозиції?


vце цілий рядок книги (зокрема, moby dick), я йду слово за словом, а не знак за символом. Отже, деякі слова можуть мати знак "," в кінці, тому "гідність" не відображається з "гідність".
KDecker


Лолкс - ти отримував таку ж домашню вправу до співбесіди, як я? Знайдіть у Moby Dick 50 найбільш вживаних слів і повідомте про їх частоту. Я зробив це в C ++, IIRC
Моуг каже, відновити Моніку

1
@Mawg Це була вправа в моєму класі "хмарних обчислень" середнього рівня.
KDecker

Відповіді:


128

Використовуйте re.sub

import re

regex = re.compile('[^a-zA-Z]')
#First parameter is the replacement, second parameter is your input string
regex.sub('', 'ab3d*E')
#Out: 'abdE'

Крім того, якщо ви хочете видалити лише певний набір символів (як апостроф може бути нормальним у вашому введенні ...)

regex = re.compile('[,\.!?]') #etc.

Хм, я цілком можу це відстежити, але як щодо шаблону, щоб видалити всі небуквено-цифрові символи, за винятком пробілів?
KDecker,

1
Просто додайте пробіл у свій клас колекції. тобто ^a-zA-Z замість просто^a-zA-Z
limasxgoesto0

Якщо вас також не турбують нові рядки, у такому випадку a-zA-Z \n. Я намагаюся знайти регулярний вираз, який би поєднав обидва в одне, але використовуючи \wабо \Wне даючи мені бажаної поведінки. Можливо, вам просто доведеться додати, \nякщо це так.
limasxgoesto0

Ааа, символ нового рядка. Саме в цьому моя проблема, я порівнював свої результати з даними результатами, і все ще не працював. Я думаю, це моє питання! Дякую // Хм, я спробував із новим рядком, однакові результати, я думаю, є ще один, якого мені бракує .. // Duhhh ... Великі та малі літери ... // Дякую за допомогу, зараз чудово працює!
KDecker

48

Якщо ви віддаєте перевагу не використовувати регулярний вираз, спробуйте

''.join([i for i in s if i.isalpha()])

як мені приєднатися до цього? з ''. приєднатися?
print

Ого, це те, що я шукав. Це враховує кандзі, хірагану, катакану тощо. слава
root163

34

Ви можете використовувати функцію re.sub (), щоб видалити такі символи:

>>> import re
>>> re.sub("[^a-zA-Z]+", "", "ABC12abc345def")
'ABCabcdef'

re.sub (Шаблон відповідності, ЗАМІНИ РЯДКУ, НАПРЯМУ ДЛЯ ПОШУКУ)

  • "[^a-zA-Z]+" - шукати будь-яку групу символів, які НЕ a-zA-z.
  • "" - Замініть відповідні символи на ""

Зверніть увагу, що це також призведе до видалення наголошених літер: ãâàáéèçõ тощо
Бред Аренс,

19

Спробуйте:

s = ''.join(filter(str.isalnum, s))

Це забере кожен символ із рядка, збереже лише буквено-цифрові та побудує з них рядок.


1
Ця відповідь може використати набагато більше пояснень та посилань на відповідну документацію.
pdoherty926

4

Найшвидший метод - регулярний вираз

#Try with regex first
t0 = timeit.timeit("""
s = r2.sub('', st)

""", setup = """
import re
r2 = re.compile(r'[^a-zA-Z0-9]', re.MULTILINE)
st = 'abcdefghijklmnopqrstuvwxyz123456789!@#$%^&*()-=_+'
""", number = 1000000)
print(t0)

#Try with join method on filter
t0 = timeit.timeit("""
s = ''.join(filter(str.isalnum, st))

""", setup = """
st = 'abcdefghijklmnopqrstuvwxyz123456789!@#$%^&*()-=_+'
""",
number = 1000000)
print(t0)

#Try with only join
t0 = timeit.timeit("""
s = ''.join(c for c in st if c.isalnum())

""", setup = """
st = 'abcdefghijklmnopqrstuvwxyz123456789!@#$%^&*()-=_+'
""", number = 1000000)
print(t0)


2.6002226710006653 Method 1 Regex
5.739747313000407 Method 2 Filter + Join
6.540099570000166 Method 3 Join

0

Бажано використовувати модуль PyPi,regex якщо ви плануєте відповідати певним класам властивостей Unicode. Ця бібліотека також виявилася більш стабільною, особливо при обробці великих текстів, і дає стабільні результати в різних версіях Python. Все, що вам потрібно зробити, це підтримувати його актуальність.

Якщо ви встановите його (за допомогою pip intall regexабо pip3 install regex), ви можете використовувати

import regex
print ( regex.sub(r'\P{L}+', '', 'ABCŁąć1-2!Абв3§4“5def”') )
// => ABCŁąćАбвdef

щоб видалити всі фрагменти з 1 або більше символів, крім букв Unicode text. Дивіться онлайн-версію Python . Ви також можете використовувати, "".join(regex.findall(r'\p{L}+', 'ABCŁąć1-2!Абв3§4“5def”'))щоб отримати той самий результат.

У Python re, щоб зіставити будь-яку букву Юнікоду, можна використовувати [^\W\d_]конструкцію ( Відповідати будь-якій букві Юнікоду ? )

Отже, щоб видалити всі небуквені символи, ви можете або зіставити всі літери, і приєднати результати:

result = "".join(re.findall(r'[^\W\d_]', text))

Або видаліть усі символи, крім тих, що відповідають [^\W\d_]:

result = re.sub(r'([^\W\d_])|.', r'\1', text, re.DOTALL)

Дивіться демонстрацію регулярних виразів онлайн . Однак ви можете отримати несумісні результати в різних версіях Python, оскільки стандарт Unicode розвивається, і набір символів, що відповідає, \wбуде залежати від версії Python. Використання regexбібліотеки PyPi настійно рекомендується для отримання стабільних результатів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.