it-roy-ru.com

Удалить определенные символы из строки в Python

Я пытаюсь удалить определенные символы из строки, используя Python. Это код, который я использую прямо сейчас. К сожалению, похоже, что ничего не делает со строкой.

for char in line:
    if char in " ?.!/;:":
        line.replace(char,'')

Как мне сделать это правильно?

415
Matt Phillips

Строки в Python являются immutable (не могут быть изменены). Из-за этого эффект line.replace(...) заключается просто в создании новой строки, а не в изменении старой. Вам нужно rebind (назначить) его для line, чтобы эта переменная приняла новое значение с удалением этих символов.

Кроме того, то, как вы это делаете, будет относительно медленным. Это также, вероятно, будет немного смущать опытных питонаторов, которые увидят дважды вложенную структуру и на мгновение подумают, что происходит нечто более сложное.

Начиная с Python 2.6 и более новых версий Python 2.x *, вы можете вместо этого использовать str.translate , (но читайте дальше для различий Python 3):

line = line.translate(None, '[email protected]#$')

или замена регулярного выражения на re.sub

import re
line = re.sub('[[email protected]#$]', '', line)

Символы, заключенные в квадратные скобки, составляют класс символов . Любые символы в line, которые находятся в этом классе, заменяются вторым параметром на sub: пустая строка.

В Python 3 строки - это Юникод. Вам придется переводить немного по-другому. kevpie упоминает об этом в комментарии к одному из ответов, и это отмечено в документации для str.translate .

При вызове метода translate строки Unicode вы не можете передать второй параметр, который мы использовали выше. Вы также не можете передать None в качестве первого параметра или даже таблицу перевода из string.maketrans. Вместо этого вы передаете словарь в качестве единственного параметра. Этот словарь отображает порядковые значения символов (т. Е. Результат вызова ord для них) с порядковыми значениями символов, которые должны их заменить, или - полезно для нас - None, чтобы указать, что они должны быть удаленным.

Таким образом, чтобы сделать вышеупомянутый танец со строкой Unicode, вы бы назвали что-то вроде

translation_table = dict.fromkeys(map(ord, '[email protected]#$'), None)
unicode_line = unicode_line.translate(translation_table)

Здесь dict.fromkeys и map используются для краткой генерации словаря, содержащего

{ord('!'): None, ord('@'): None, ...}

Еще проще, так как другой ответ ставит это , создайте словарь на месте:

unicode_line = unicode_line.translate({ord(c): None for c in '[email protected]#$'})

* для совместимости с более ранними Pythons, вы можете создать «нулевую» таблицу перевода для передачи вместо None:

import string
line = line.translate(string.maketrans('', ''), '[email protected]#$')

Здесь string.maketrans используется для создания таблицы перевода, которая представляет собой просто строку, содержащую символы со порядковыми значениями от 0 до 255.

528
intuited

Я здесь упускаю суть или это просто следующее:

>>> string = "ab1cd1ef"
>>> string.replace("1","")
'abcdef'
>>>

Поместите это в цикл:

>>>
>>> a = "[email protected]#d$"
>>> b = "[email protected]#$"
>>> for char in b:
...     a = a.replace(char,"")
...
>>> print a
abcd
>>>
180
gsbabil
>>> line = "abc#@!?efg12;:?"
>>> ''.join( c for c in line if  c not in '?:!/;' )
'abc#@efg12'
37
ghostdog74

Легко peasy с re.sub в Python 3.5

re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)

Пример

>>> import re

>>> line = 'Q: Do I write ;/.??? No!!!'

>>> re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)
'QDoIwriteNo'

Объяснение

В регулярных выражениях (regex) | является логическим OR, а \ экранирует пробелы и специальные символы, которые могут быть фактическими командами regex. sub означает замену.

20
Serge Stroobandt

Для обратного требования только разрешать определенных символов в строке вы можете использовать регулярные выражения с оператором дополнения набора [^ABCabc]. Например, чтобы удалить все, кроме букв ascii, цифр и дефиса:

>>> import string
>>> import re
>>>
>>> phrase = '  There were "nine" (9) chick-peas in my pocket!!!      '
>>> allow = string.letters + string.digits + '-'
>>> re.sub('[^%s]' % allow, '', phrase)

'Therewerenine9chick-peasinmypocket'

From документация по регулярным выражениям python :

Символы, которые не находятся в пределах диапазона, могут быть сопоставлены путем дополнения набор. Если первый символ набора - '^', все символы которые не в наборе будут сопоставлены. Например, [^5] будет соответствовать любой символ, кроме «5», и [^^] будет соответствовать любому символу, кроме '^'. ^ не имеет особого значения, если это не первый символ в задавать.

18
cod3monk3y

У Аскера почти было это. Как и большинство вещей в Python, ответ проще, чем вы думаете.

>>> line = "H E?.LL!/;O:: "  
>>> for char in ' ?.!/;:':  
...  line = line.replace(char,'')  
...
>>> print line
HELLO

Вам не нужно выполнять вложенный цикл if/for, но вам НЕОБХОДИМО проверять каждый символ отдельно.

18
mgold
line = line.translate(None, " ?.!/;:")
14
Muhammad Alkarouri
>>> s = 'a1b2c3'
>>> ''.join(c for c in s if c not in '123')
'abc'
10
eatkin

Строки неизменны в Python. Метод replace возвращает новую строку после замены. Пытаться:

for char in line:
    if char in " ?.!/;:":
        line = line.replace(char,'')
7
Greg Hewgill

Используя filter , вам понадобится всего одна строка

line = filter(lambda char: char not in " ?.!/;:", line)

Это обрабатывает строку как итеративную и проверяет каждый символ, если lambda возвращает True:

>>> help(filter)
Help on built-in function filter in module __builtin__:

filter(...)
    filter(function or None, sequence) -> list, Tuple, or string

    Return those items of sequence for which function(item) is true.  If
    function is None, return the items that are true.  If sequence is a Tuple
    or string, return the same type, else return a list.
5
serv-inc

Я был удивлен, что никто еще не рекомендовал использовать встроенный фильтр функция.

    import operator
    import string # only for the example you could use a custom string

    s = "1212edjaq"

Скажем, мы хотим отфильтровать все, что не является числом. Использование встроенного метода фильтра «... эквивалентно выражению генератора (элемент для элемента в итерируемой функции (элемент))» [ Python 3 Builtins: Фильтр ]

    sList = list(s)
    intsList = list(string.digits)
    obj = filter(lambda x: operator.contains(intsList, x), sList)))

В Python 3 это возвращает 

    >>  <filter object @ hex>

Чтобы получить печатную строку,

    nums = "".join(list(obj))
    print(nums)
    >> "1212"

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

Обновление

Логично, что поскольку фильтр работает, вы также можете использовать понимание списков, и из того, что я прочитал, он должен быть более эффективным, потому что лямбды - это управляющие хедж-фондов Уолл-стрит в мире функций программирования. Еще одним плюсом является то, что это однострочник, который не требует импорта. Например, используя ту же строку 's', определенную выше,

      num = "".join([i for i in s if i.isdigit()])

Вот и все. Возвращаемым будет строка всех символов, которые являются цифрами в исходной строке.

Если у вас есть определенный список допустимых/неприемлемых символов, вам нужно только отрегулировать часть «если» в понимании списка.

      target_chars = "".join([i for i in s if i in some_list]) 

или, в качестве альтернативы,

      target_chars = "".join([i for i in s if i not in some_list])
5
Dan Temkin
>>> # Character stripping
>>> a = '?abcd1234!!'
>>> t.lstrip('?')
'abcd1234!!'
>>> t.strip('?!')
'abcd1234'
4
Arihant Bansal

Вот несколько возможных способов решения этой задачи:

def attempt1(string):
    return "".join([v for v in string if v not in ("a", "e", "i", "o", "u")])


def attempt2(string):
    for v in ("a", "e", "i", "o", "u"):
        string = string.replace(v, "")
    return string


def attempt3(string):
    import re
    for v in ("a", "e", "i", "o", "u"):
        string = re.sub(v, "", string)
    return string


def attempt4(string):
    return string.replace("a", "").replace("e", "").replace("i", "").replace("o", "").replace("u", "")


for attempt in [attempt1, attempt2, attempt3, attempt4]:
    print(attempt("murcielago"))

PS: вместо использования "?.!/;:" в примерах используются гласные ... и да, "murcielago" - это испанское слово, говорящее "летучая мышь ... смешное слово", так как оно содержит все гласные :)

PS2: Если вы заинтересованы в производительности, вы можете измерить эти попытки с помощью простого кода:

import timeit


K = 1000000
for i in range(1,5):
    t = timeit.Timer(
        f"attempt{i}('murcielago')",
        setup=f"from __main__ import attempt{i}"
    ).repeat(1, K)
    print(f"attempt{i}",min(t))

В моей коробке вы получите:

attempt1 2.2334518376057244
attempt2 1.8806643818474513
attempt3 7.214925774955572
attempt4 1.7271184513757465

Так что кажется, что try4 является самым быстрым для этого конкретного ввода.

3
BPL

Вот моя Python 2/3 совместимая версия. С тех пор как переводчик API изменился. 

def remove(str_, chars):
    """Removes each char in `chars` from `str_`.

    Args:
        str_: String to remove characters from
        chars: String of to-be removed characters

    Returns:
        A copy of str_ with `chars` removed

    Example:
            remove("What?!?: darn;", " ?.!:;") => 'Whatdarn'
    """
    try:
        # Python2.x
        return str_.translate(None, chars)
    except TypeError:
        # Python 3.x
        table = {ord(char): None for char in chars}
        return str_.translate(table)
3
Bryce Guinta

Вы также можете использовать функцию для замены регулярного выражения другого типа или другого шаблона с использованием списка. При этом вы можете смешивать регулярные выражения, класс символов и действительно базовый текстовый шаблон. Это действительно полезно, когда вам нужно заменить много элементов, таких как HTML.

* Примечание: работает с Python 3.x

import re  # Regular expression library


def string_cleanup(x, notwanted):
    for item in notwanted:
        x = re.sub(item, '', x)
    return x

line = "<title>My example: <strong>A text %very% $clean!!</strong></title>"
print("Uncleaned: ", line)

# Get rid of html elements
html_elements = ["<title>", "</title>", "<strong>", "</strong>"]
line = string_cleanup(line, html_elements)
print("1st clean: ", line)

# Get rid of special characters
special_chars = ["[[email protected]#$]", "%"]
line = string_cleanup(line, special_chars)
print("2nd clean: ", line)

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

Результат:

Uncleaned:  <title>My example: <strong>A text %very% $clean!!</strong></title>
1st clean:  My example: A text %very% $clean!!
2nd clean:  My example: A text very clean
1
Djidiouf
#!/usr/bin/python
import re

strs = "how^ much for{} the maple syrup? $20.99? That's[] ricidulous!!!"
print strs
nstr = re.sub(r'[?|$|.|!|a|b]',r' ',strs)#i have taken special character to remove but any #character can be added here
print nstr
nestr = re.sub(r'[^a-zA-Z0-9 ]',r'',nstr)#for removing special character
print nestr
1
pkm

Как насчет этого:

def text_cleanup(text):
    new = ""
    for i in text:
        if i not in " ?.!/;:":
            new += i
    return new
1
Wariat

Вы должны переназначить переменную str:

for char in line:
if char in " ?.!/;:":
    line = line.replace(char,'')
1
Anastasia Churyk

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

words = "things"
removed = "%s%s" % (words[:3], words[-1:])

Это приведет к тому, что слово «this» будет «удалено».

Форматирование может быть очень полезно для печати переменных в середине строки печати. Он может вставить любой тип данных, используя% , за которым следует тип данных переменной; все типы данных могут использовать% s , а числа с плавающей запятой (или десятичные числа) и целые числа могут использовать% d

Нарезка может использоваться для сложного контроля над строками. Когда я ставлю words [: 3] , это позволяет мне выбрать все символы в строке с начала (двоеточие перед числом, это будет означать «от начала до») до 4-го символа ( включает в себя 4-й символ). Причина 3 равна до 4-й позиции, потому что Python начинается с 0. Затем, когда я ставлю Word [-1:] , это означает, что 2-й последний символ до конца (двоеточие находится за числом). Установка -1 приведет к тому, что Python будет считаться с последнего символа, а не с первого. Опять же, Python будет начинаться с 0. Итак, Word [-1:] в основном означает «от второго последнего символа до конца строки.

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

Если я хочу удалить несколько последовательных символов, я просто сдвигаю числа в [] (часть среза). Или, если я хочу удалить несколько символов из разных позиций, я могу просто объединить несколько слайсов одновременно.

Примеры:

 words = "control"
 removed = "%s%s" % (words[:2], words[-2:])

удалено равно "круто".

words = "impacts"
removed = "%s%s%s" % (words[1], words[3:5], words[-1])

удалено равно 'macs'.

В этом случае [3: 5] означает символ в позиции 3 через символ в позиции 5 (исключая символ в конечной позиции). 

Помните, Python начинает считать с 0, так что вам тоже нужно будет.

1
oisinvg

Ниже один .. без использования концепции регулярных выражений .. 

ipstring ="text with [email protected]#$^&*( ends here"
opstring=''
for i in ipstring:
    if i.isalnum()==1 or i==' ':
        opstring+=i
    pass
print opstring
0
Sadheesh

Даже приведенный ниже подход работает

line = "a,b,c,d,e"
alpha = list(line)
        while ',' in alpha:
            alpha.remove(',')
finalString = ''.join(alpha)
print(finalString)

вывод >> abcde

0
M2skills

вы можете использовать набор

    charlist = list(set(string.digits+string.ascii_uppercase) - set('10IO'))
    return ''.join([random.SystemRandom().choice(charlist) for _ in range(passlen)])
0
Xu Zhenlei

В Python 3.5

например.,

os.rename(file_name, file_name.translate({ord(c): None for c in '0123456789'}))

Удалить все числа из строки 

0
BonieSV

Рекурсивное разбиение: s = строка; символы = символы для удаления

def strip(s,chars):
if len(s)==1:
    return "" if s in chars else s
return strip(s[0:int(len(s)/2)],chars) +  strip(s[int(len(s)/2):len(s)],chars)

пример: 

print(strip("Hello!","lo"))    #He!
0
matt

Попробуй это:

def rm_char(original_str, need2rm):
    ''' Remove charecters in "need2rm" from "original_str" '''
    return original_str.translate(str.maketrans('','',need2rm))

Этот метод хорошо работает в Python 3.5.2

0
Joseph Lee