Menghapus daftar karakter dalam string

217

Saya ingin menghapus karakter dalam string dengan python:

string.replace(',', '').replace("!", '').replace(":", '').replace(";", '')...

Tapi saya punya banyak karakter yang harus saya hapus. Saya memikirkan daftar

list = [',', '!', '.', ';'...]

Tetapi bagaimana saya bisa menggunakan listuntuk mengganti karakter di string?

Laura
sumber
6
Lihat stackoverflow.com/questions/1919096/… untuk berbagai solusi dan perbandingan yang bagus.
Martijn de Milliano
Sangat disayangkan bahwa Python (yang dikatakan datang dengan baterai termasuk) tidak menangani kasus penggunaan ini di luar kotak. Fungsi PHP str_replace melakukannya - Anda dapat melewatkan array sebagai argumen pertama dan string sebagai argumen kedua ( php.net/manual/pl/function.str-replace.php ).
JustAC0der

Jawaban:

264

Jika Anda menggunakan python2 dan input Anda berupa string (bukan unicodes), metode yang terbaik adalah str.translate:

>>> chars_to_remove = ['.', '!', '?']
>>> subj = 'A.B!C?'
>>> subj.translate(None, ''.join(chars_to_remove))
'ABC'

Jika tidak, ada opsi berikut untuk dipertimbangkan:

A. Iterasi char subjek dengan char, hilangkan karakter yang tidak diinginkan dan joindaftar yang dihasilkan:

>>> sc = set(chars_to_remove)
>>> ''.join([c for c in subj if c not in sc])
'ABC'

(Perhatikan bahwa versi generator ''.join(c for c ...) akan kurang efisien).

B. Buat ekspresi reguler dengan cepat dan re.subdengan string kosong:

>>> import re
>>> rx = '[' + re.escape(''.join(chars_to_remove)) + ']'
>>> re.sub(rx, '', subj)
'ABC'

( re.escapememastikan bahwa karakter suka ^atau ]tidak akan merusak ekspresi reguler).

C. Gunakan varian pemetaantranslate :

>>> chars_to_remove = [u'δ', u'Γ', u'ж']
>>> subj = u'AжBδCΓ'
>>> dd = {ord(c):None for c in chars_to_remove}
>>> subj.translate(dd)
u'ABC'

Kode pengujian lengkap dan timing:

#coding=utf8

import re

def remove_chars_iter(subj, chars):
    sc = set(chars)
    return ''.join([c for c in subj if c not in sc])

def remove_chars_re(subj, chars):
    return re.sub('[' + re.escape(''.join(chars)) + ']', '', subj)

def remove_chars_re_unicode(subj, chars):
    return re.sub(u'(?u)[' + re.escape(''.join(chars)) + ']', '', subj)

def remove_chars_translate_bytes(subj, chars):
    return subj.translate(None, ''.join(chars))

def remove_chars_translate_unicode(subj, chars):
    d = {ord(c):None for c in chars}
    return subj.translate(d)

import timeit, sys

def profile(f):
    assert f(subj, chars_to_remove) == test
    t = timeit.timeit(lambda: f(subj, chars_to_remove), number=1000)
    print ('{0:.3f} {1}'.format(t, f.__name__))

print (sys.version)
PYTHON2 = sys.version_info[0] == 2

print ('\n"plain" string:\n')

chars_to_remove = ['.', '!', '?']
subj = 'A.B!C?' * 1000
test = 'ABC' * 1000

profile(remove_chars_iter)
profile(remove_chars_re)

if PYTHON2:
    profile(remove_chars_translate_bytes)
else:
    profile(remove_chars_translate_unicode)

print ('\nunicode string:\n')

if PYTHON2:
    chars_to_remove = [u'δ', u'Γ', u'ж']
    subj = u'AжBδCΓ'
else:
    chars_to_remove = ['δ', 'Γ', 'ж']
    subj = 'AжBδCΓ'

subj = subj * 1000
test = 'ABC' * 1000

profile(remove_chars_iter)

if PYTHON2:
    profile(remove_chars_re_unicode)
else:
    profile(remove_chars_re)

profile(remove_chars_translate_unicode)

Hasil:

2.7.5 (default, Mar  9 2014, 22:15:05) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)]

"plain" string:

0.637 remove_chars_iter
0.649 remove_chars_re
0.010 remove_chars_translate_bytes

unicode string:

0.866 remove_chars_iter
0.680 remove_chars_re_unicode
1.373 remove_chars_translate_unicode

---

3.4.2 (v3.4.2:ab2c023a9432, Oct  5 2014, 20:42:22) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]

"plain" string:

0.512 remove_chars_iter
0.574 remove_chars_re
0.765 remove_chars_translate_unicode

unicode string:

0.817 remove_chars_iter
0.686 remove_chars_re
0.876 remove_chars_translate_unicode

(Sebagai catatan, angka untuk remove_chars_translate_bytesmungkin memberi kita petunjuk mengapa industri enggan mengadopsi Unicode untuk waktu yang lama).

georg
sumber
1
Metode kedua menimbulkan kesalahan TypeError: translate() takes exactly one argument (2 given). Tampaknya dibutuhkan dikt sebagai argumen.
antonavy
@ Cantonavy - solusi 2 tidak berfungsi - tetapi hanya string yang bukan unicode (yang membutuhkan terjemahan berbeda () diperlukan
FuzzyAmi
112

Anda bisa menggunakan str.translate():

s.translate(None, ",!.;")

Contoh:

>>> s = "asjo,fdjk;djaso,oio!kod.kjods;dkps"
>>> s.translate(None, ",!.;")
'asjofdjkdjasooiokodkjodsdkps'
Sven Marnach
sumber
19
@ thg435: Tidak ada yang memintanya, tetapi:s.translate(dict.fromkeys(map(ord, u",!.;")))
Sven Marnach
2
Jawaban simultan (dan @ PraveenGollakota) ini persis seperti yang diminta @Laura dan harus menjadi jawaban yang lebih disukai.
Hobs
7
mengapa python3: TypeError: translate () mengambil tepat satu argumen (2 diberikan)
Gank
2
@Gank: unicode.translate()Metode ini memiliki parameter yang berbeda dari str.translate()metode ini. Gunakan varian dalam komentar di atas untuk objek Unicode.
Sven Marnach
@ SvenMarnach apa itu peta (ord, u ",!.;"))? dan apakah kamu berdiri untuk unicode?
Jun711
34

Anda dapat menggunakan metode terjemahan .

s.translate(None, '!.;,')
Praveen Gollakota
sumber
16
''.join(c for c in myString if not c in badTokens)
ninjagecko
sumber
Berguna dalam kasus serupa yang tidak didasarkan pada karakter dan string +1
Wolf
12

Jika Anda menggunakan python3 dan mencaritranslate solusinya - fungsi berubah dan sekarang mengambil 1 parameter, bukan 2.

Parameter itu adalah sebuah tabel (bisa berupa kamus) di mana setiap kunci adalah ordinal Unicode (int) dari karakter yang akan ditemukan dan nilainya adalah penggantian (dapat berupa Unicode ordinal atau string untuk memetakan kunci ke).

Ini adalah contoh penggunaan:

>>> list = [',', '!', '.', ';']
>>> s = "This is, my! str,ing."
>>> s.translate({ord(x): '' for x in list})
'This is my string'
Dekel
sumber
8

Pendekatan lain menggunakan regex:

''.join(re.split(r'[.;!?,]', s))
alan
sumber
7

Kenapa bukan loop sederhana?

for i in replace_list:
    string = string.replace(i, '')

Juga, hindari penamaan daftar 'daftar'. Ini mengesampingkan fungsi bawaan list.

aikid
sumber
6

Anda bisa menggunakan sesuatu seperti ini

def replace_all(text, dic):
  for i, j in dic.iteritems():
    text = text.replace(i, j)
  return text

Kode ini bukan milik saya dan berasal dari sini artikel yang bagus dan dibahas secara mendalam

kehormatan krystan
sumber
3

Juga topik menarik tentang penghapusan aksen UTF-8 dari string yang mengubah char menjadi char standar yang tidak menonjolkan:

Apa cara terbaik untuk menghilangkan aksen dalam string unicode python?

ekstrak kode dari topik:

import unicodedata

def remove_accents(input_str):
    nkfd_form = unicodedata.normalize('NFKD', input_str)
    return u"".join([c for c in nkfd_form if not unicodedata.combining(c)])
Sylvain
sumber
3

Mungkin cara yang lebih modern dan fungsional untuk mencapai apa yang Anda inginkan:

>>> subj = 'A.B!C?'
>>> list = set([',', '!', '.', ';', '?'])
>>> filter(lambda x: x not in list, subj)
'ABC'

harap dicatat bahwa untuk tujuan khusus ini cukup sulit, tetapi sekali Anda membutuhkan kondisi yang lebih kompleks, filter menjadi berguna

kerusuhan
sumber
Juga perhatikan bahwa ini bisa dengan mudah dilakukan dengan daftar pemahaman, yang jauh lebih pythonic menurut saya.
Kerusuhan
3

cara sederhana,

import re
str = 'this is string !    >><< (foo---> bar) @-tuna-#   sandwich-%-is-$-* good'

// condense multiple empty spaces into 1
str = ' '.join(str.split()

// replace empty space with dash
str = str.replace(" ","-")

// take out any char that matches regex
str = re.sub('[!@#$%^&*()_+<>]', '', str)

keluaran:

this-is-string--foo----bar--tuna---sandwich--is---good

perfecto25
sumber
1

Bagaimana dengan ini - satu liner.

reduce(lambda x,y : x.replace(y,"") ,[',', '!', '.', ';'],";Test , ,  !Stri!ng ..")
Akshay Hazari
sumber
1

Saya pikir ini cukup sederhana dan akan dilakukan!

list = [",",",","!",";",":"] #the list goes on.....

theString = "dlkaj;lkdjf'adklfaj;lsd'fa'dfj;alkdjf" #is an example string;
newString="" #the unwanted character free string
for i in range(len(TheString)):
    if theString[i] in list:
        newString += "" #concatenate an empty string.
    else:
        newString += theString[i]

ini adalah salah satu cara untuk melakukannya. Tetapi jika Anda bosan menyimpan daftar karakter yang ingin Anda hapus, Anda sebenarnya dapat melakukannya dengan menggunakan nomor urut string yang Anda ulangi. nomor pesanan adalah nilai ascii dari karakter itu. angka ascii untuk 0 sebagai char adalah 48 dan angka ascii untuk huruf kecil z adalah 122 jadi:

theString = "lkdsjf;alkd8a'asdjf;lkaheoialkdjf;ad"
newString = ""
for i in range(len(theString)):
     if ord(theString[i]) < 48 or ord(theString[i]) > 122: #ord() => ascii num.
         newString += ""
     else:
        newString += theString[i]
Hiskel Kelemework
sumber
0

Hari-hari ini saya terjun ke skema, dan sekarang saya pikir saya baik dalam pengulangan dan eval. HA HA HA. Bagikan saja beberapa cara baru:

pertama, eval it

print eval('string%s' % (''.join(['.replace("%s","")'%i for i in replace_list])))

kedua, ulangi saja

def repn(string,replace_list):
    if replace_list==[]:
        return string
    else:
        return repn(string.replace(replace_list.pop(),""),replace_list)

print repn(string,replace_list)

Hei, jangan downvote. Saya hanya ingin berbagi ide baru.

tcpiper
sumber
0

Saya sedang memikirkan solusi untuk ini. Pertama saya akan membuat input string sebagai daftar. Maka saya akan mengganti item daftar. Kemudian dengan menggunakan perintah join, saya akan mengembalikan daftar sebagai string. Kode bisa seperti ini:

def the_replacer(text):
    test = []    
    for m in range(len(text)):
        test.append(text[m])
        if test[m]==','\
        or test[m]=='!'\
        or test[m]=='.'\
        or test[m]=='\''\
        or test[m]==';':
    #....
            test[n]=''
    return ''.join(test)

Ini akan menghapus apa pun dari string. Apa pendapatmu tentang itu?

Sheikh Ahmad Shah
sumber
0

Berikut ini more_itertoolspendekatannya:

import more_itertools as mit


s = "A.B!C?D_E@F#"
blacklist = ".!?_@#"

"".join(mit.flatten(mit.split_at(s, pred=lambda x: x in set(blacklist))))
# 'ABCDEF'

Di sini kami membagi berdasarkan item yang ditemukan di blacklist, ratakan hasilnya dan bergabung dengan string.

pylang
sumber
0

Python 3, implementasi pemahaman daftar baris tunggal.

from string import ascii_lowercase # 'abcdefghijklmnopqrstuvwxyz'
def remove_chars(input_string, removable):
  return ''.join([_ for _ in input_string if _ not in removable])

print(remove_chars(input_string="Stack Overflow", removable=ascii_lowercase))
>>> 'S O'
John Forbes
sumber
0

Hapus *%, & @! dari string di bawah ini:

s = "this is my string,  and i will * remove * these ** %% "
new_string = s.translate(s.maketrans('','','*%,&@!'))
print(new_string)

# output: this is my string  and i will  remove  these  
Biplob Das
sumber