Удаление списка символов в строке


217

Я хочу удалить символы в строке в Python:

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

Но у меня есть много персонажей, которые я должен удалить. Я думал о списке

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

Но как я могу использовать listдля замены символов в string?


6
См. Stackoverflow.com/questions/1919096/… для различных решений и хорошего сравнения.
Мартейн де Миллиано

Жаль, что Python (который, как говорят, идет с включенными батареями) не обрабатывает этот вариант использования из коробки. Функция PHP str_replace делает это - вы можете передать массив в качестве первого аргумента и строку в качестве второго ( php.net/manual/pl/function.str-replace.php ).
JustAC0der

Ответы:


265

Если вы используете python2 и ваши входные данные являются строками (а не юникодами), абсолютно лучший метод str.translate:

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

В противном случае есть следующие варианты для рассмотрения:

A. Переберите тему char по символу, пропустите ненужные символы и joinполучившийся список:

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

(Обратите внимание, что версия генератора ''.join(c for c ...)будет менее эффективной).

Б. Создайте регулярное выражение на лету и re.subс пустой строкой:

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

( re.escapeгарантирует, что символы любят ^или ]не будут нарушать регулярное выражение).

C. Используйте вариант отображенияtranslate :

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

Полный код тестирования и тайминги:

#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)

Полученные результаты:

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

(Как примечание, цифра remove_chars_translate_bytesможет дать нам подсказку, почему индустрия не хотела принимать Unicode в течение столь длительного времени).


1
Второй метод вызывает ошибку TypeError: translate() takes exactly one argument (2 given). Видимо, он принимает в качестве аргумента диктат.
антонави

@antonavy - 2-е решение работает - но только строка не является юникодом (для которой нужен другой translate ())
FuzzyAmi

112

Вы можете использовать str.translate():

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

Пример:

>>> s = "asjo,fdjk;djaso,oio!kod.kjods;dkps"
>>> s.translate(None, ",!.;")
'asjofdjkdjasooiokodkjodsdkps'

19
@ thg435: Никто не просил об этом, но в любом случае:s.translate(dict.fromkeys(map(ord, u",!.;")))
Свен Марнах

2
Этот (и @ PraveenGollakota) одновременный ответ - именно то, о чем @Laura просил, и должен быть предпочтительным ответом (ами).
варенье

7
почему python3: TypeError: translate () принимает ровно один аргумент (2 дано)
Gank

2
@Gank: unicode.translate()метод имеет параметры, отличные от str.translate()метода. Используйте вариант в комментарии выше для объектов Unicode.
Свен Марнах

@SvenMarnach что такое карта (ord, u ",!.;))? а ты за юникод?
Jun711


16
''.join(c for c in myString if not c in badTokens)

Полезно в подобных случаях, не основанных на символах и строках +1
Wolf

12

Если вы используете python3 и ищете translateрешение - функция была изменена и теперь принимает 1 параметр вместо 2.

Этот параметр является таблицей (может быть словарем), где каждый ключ - это порядковый номер Unicode (int) искомого символа, а значение является заменой (может быть либо порядковый номер Unicode, либо строка для сопоставления ключа).

Вот пример использования:

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

8

Другой подход с использованием регулярных выражений:

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

7

Почему не простой цикл?

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

Кроме того, избегайте именования списков «список». Переопределяет встроенную функцию list.


6

Вы могли бы использовать что-то вроде этого

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

Этот код не является моим собственным и происходит от здесь свою большую статью и dicusses в глубине делает это


3

Также интересную тему по удалению UTF-8 с ударением образуют строки, конвертирующие char в их стандартные неакцентированные char:

Каков наилучший способ удалить акценты в строке Python Unicode?

Извлечение кода из темы:

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)])

3

Возможно, более современный и функциональный способ достичь того, что вы хотите:

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

обратите внимание, что для этой конкретной цели это довольно излишне, но как только вам понадобятся более сложные условия, фильтр пригодится


Также обратите внимание, что это можно сделать с помощью списочных представлений, что, на мой взгляд, гораздо более питонно.
Мятеж

3

простой способ,

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)

вывод:

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



1

Я думаю, что это достаточно просто и будет делать!

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]

это один из способов сделать это. Но если вам надоело хранить список символов, которые вы хотите удалить, вы можете сделать это, используя порядковый номер строк, через которые вы проходите. порядковый номер является значением ascii этого символа. число ascii для 0 в качестве символа равно 48, а число ascii для нижнего регистра z равно 122, поэтому:

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]

0

В эти дни я погружаюсь в схему, и теперь я думаю, что хорош в повторении и оценке. Хахаха. Просто поделитесь некоторыми новыми способами:

во-первых, оценить это

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

во-вторых, повторить это

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)

Эй, не отрицай. Я просто хочу поделиться какой-то новой идеей.


0

Я думаю о решении для этого. Сначала я бы сделал строку ввода в виде списка. Тогда я бы заменил пункты списка. Затем с помощью команды соединения я верну список в виде строки. Код может быть таким:

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)

Это позволит удалить что-нибудь из строки. Что ты об этом думаешь?


0

Вот more_itertoolsподход:

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'

Здесь мы разбиваем элементы, найденные в blacklist, сглаживаем результаты и присоединяемся к строке.


0

Python 3, реализация понимания однострочного списка.

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'

0

Удалять *%,&@! снизу строка:

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  
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.