Python, hapus semua karakter non-alfabet dari string

90

Saya sedang menulis program penghitungan kata MapReduce python. Masalahnya adalah bahwa ada banyak karakter non-alfabet berserakan dalam data, saya telah menemukan posting ini Menghapus semuanya kecuali karakter alfanumerik dari string dengan Python yang menunjukkan solusi yang bagus menggunakan regex, tetapi saya tidak yakin bagaimana cara menerapkannya

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

Saya khawatir saya tidak yakin bagaimana menggunakan perpustakaan reatau bahkan regex dalam hal ini. Saya tidak yakin bagaimana menerapkan pola regex ke string masuk (baris buku) vdengan benar untuk mengambil baris baru tanpa karakter non-alfanumerik.

Saran?

KDecker
sumber
vadalah keseluruhan baris dari sebuah buku (khususnya moby dick), saya akan kata demi kata bukan karakter demi karakter. Jadi beberapa kata mungkin memiliki "," pada akhirnya jadi "penghinaan," tidak dipetakan dengan "penghinaan".
KDecker
Lolx - apakah Anda melakukan senam pra-wawancara yang sama dengan saya? Temukan 50 kata yang paling sering digunakan di Moby Dick dan laporkan frekuensinya. Saya melakukannya di C ++, IIRC
Mawg mengatakan memulihkan Monica
1
@Mawg Itu adalah latihan di kelas "Cloud Computing" saya.
KDecker

Jawaban:

128

Menggunakan 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'

Alternatifnya, jika Anda hanya ingin menghapus sekumpulan karakter tertentu (sebagai apostrof mungkin baik-baik saja dalam masukan Anda ...)

regex = re.compile('[,\.!?]') #etc.
limasxgoesto0
sumber
Hmm, saya bisa melacaknya, tapi bagaimana dengan pola untuk menghapus semua spasi non-alfanumerik?
KDecker
1
Cukup tambahkan ruang ke kelas koleksi Anda. yaitu, ^a-zA-Z bukannya hanya^a-zA-Z
limasxgoesto0
Kecuali jika Anda juga khawatir tentang baris baru, dalam hal ini a-zA-Z \n. Saya mencoba menemukan regex yang akan menggabungkan keduanya menjadi satu tetapi menggunakan \watau \Wtidak memberi saya perilaku yang diinginkan. Anda mungkin perlu menambahkan \njika itu masalahnya.
limasxgoesto0
Ahh, karakter baris baru. Di situlah letak masalah saya, saya membandingkan hasil saya dengan hasil yang diberikan dan saya masih pergi. Saya pikir itu masalah saya! Terima kasih // Hmm, saya mencobanya dengan karakter baris baru hasil yang sama, saya rasa ada yang lain yang saya lewatkan .. // Duhhh ... Huruf besar dan kecil ... // Terima kasih atas semua bantuannya, berfungsi dengan baik sekarang!
KDecker
48

Jika Anda memilih untuk tidak menggunakan regex, Anda dapat mencobanya

''.join([i for i in s if i.isalpha()])
Tad
sumber
bagaimana cara bergabung dengan ini? dengan '' .join? pencetakan hanya mendapat objek filter
PirateApp
Wow, inilah yang saya cari. Ini memperhitungkan kanji, hiragana, katakana, dll. kudos
root163
34

Anda dapat menggunakan fungsi re.sub () untuk menghapus karakter ini:

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

re.sub (POLA PERTANDINGAN, GANTI STRING, STRING UNTUK MENELUSURI)

  • "[^a-zA-Z]+" - cari kelompok karakter yang BUKAN a-zA-z.
  • "" - Ganti karakter yang cocok dengan ""
Kevin
sumber
Perhatikan bahwa ini juga akan menghapus huruf beraksen: ãâàáéèçõ, dll.
Brad Ahrens
19

Mencoba:

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

Ini akan mengambil setiap karakter dari string, hanya menyimpan karakter alfanumerik dan membangun string kembali darinya.

Mengenakan
sumber
1
Jawaban ini membutuhkan lebih banyak penjelasan dan tautan ke dokumentasi yang relevan.
pdoherty926
4

Metode tercepat adalah regex

#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
PirateApp
sumber
0

Disarankan untuk menggunakan modul PyPiregex jika Anda berencana untuk mencocokkan kelas properti Unicode tertentu. Library ini juga terbukti lebih stabil, terutama menangani teks berukuran besar, dan memberikan hasil yang konsisten di berbagai versi Python. Yang perlu Anda lakukan adalah menjaganya tetap mutakhir.

Jika Anda menginstalnya (menggunakan pip intall regexatau pip3 install regex), Anda dapat menggunakan

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

untuk menghapus semua potongan dari 1 atau lebih karakter selain huruf Unicode dari text. Lihat demo Python online . Anda juga dapat menggunakan "".join(regex.findall(r'\p{L}+', 'ABCŁąć1-2!Абв3§4“5def”'))untuk mendapatkan hasil yang sama.

Di Python re, untuk mencocokkan huruf Unicode apa pun, seseorang dapat menggunakan [^\W\d_]konstruksi ( Cocokkan huruf unicode apa saja? ).

Jadi, untuk menghapus semua karakter bukan huruf, Anda dapat mencocokkan semua huruf dan menggabungkan hasilnya:

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

Atau, hapus semua karakter selain yang cocok dengan [^\W\d_]:

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

Lihat demo regex online . Namun , Anda mungkin mendapatkan hasil yang tidak konsisten di berbagai versi Python karena standar Unicode sedang berkembang, dan kumpulan karakter yang cocok \wakan bergantung pada versi Python. Menggunakan regexpustaka PyPi sangat disarankan untuk mendapatkan hasil yang konsisten.

Wiktor Stribiżew
sumber