繁体   English   中英

从 Python 中的字符串中删除特定字符

[英]Remove specific characters from a string in Python

我正在尝试使用 Python 从字符串中删除特定字符。 这是我现在正在使用的代码。 不幸的是,它似乎对字符串没有任何作用。

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

我该如何正确执行此操作?

Python 中的字符串是不可变的(不能更改)。 因此, line.replace(...)作用只是创建一个新字符串,而不是更改旧字符串。 您需要将它重新绑定(分配)到line以便让该变量采用新值,并删除这些字符。

此外,相对而言,您这样做的方式会有点慢。 对于有经验的 Pythonators 来说,这也可能会有点混乱,他们会看到一个双重嵌套的结构,并会认为有更复杂的事情正在发生。

从 Python 2.6 和更新的 Python 2.x 版本 * 开始,您可以改用str.translate ,(请参阅下面的Python 3 答案):

line = line.translate(None, '!@#$')

或用re.sub替换正则表达式

import re
line = re.sub('[!@#$]', '', line)

括号中的字符构成一个字符类 在任何字符line ,其是在该类中被替换的第二个参数sub :一个空字符串。

Python 3 答案

在 Python 3 中,字符串是 Unicode。 您将不得不以稍微不同的方式翻译。 kevpie 在对其中一个答案的评论中提到了这一点,并在str.translate文档中str.translate

在调用 Unicode 字符串的translate方法时,不能传递我们上面使用的第二个参数。 您也不能将None作为第一个参数传递。 相反,您将转换表(通常是字典)作为唯一参数传递。 该表将字符的序数值(即对它们调用ord的结果)映射到应该替换它们的字符的序数值,或者——对我们有用—— None表示它们应该被删除。

因此,要使用 Unicode 字符串进行上述舞蹈,您可以调用类似

translation_table = dict.fromkeys(map(ord, '!@#$'), None)
unicode_line = unicode_line.translate(translation_table)

这里使用dict.fromkeysmap来简洁地生成一个字典,其中包含

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

更简单的是,正如另一个答案所说,在适当的位置创建翻译表:

unicode_line = unicode_line.translate({ord(c): None for c in '!@#$'})

或者,正如Joseph Lee 所提出的,使用str.maketrans创建相同的转换表:

unicode_line = unicode_line.translate(str.maketrans('', '', '!@#$'))

* 为了与早期的 Python 兼容,您可以创建一个“空”转换表来代替None

import string
line = line.translate(string.maketrans('', ''), '!@#$')

这里string.maketrans用于创建一个转换表,它只是一个包含序号为 0 到 255 的字符的字符串。

我在这里错过了这一点,还是只是以下几点:

string = "ab1cd1ef"
string = string.replace("1", "") 

print(string)
# result: "abcdef"

把它放在一个循环中:

a = "a!b@c#d$"
b = "!@#$"
for char in b:
    a = a.replace(char, "")

print(a)
# result: "abcd"
>>> line = "abc#@!?efg12;:?"
>>> ''.join( c for c in line if  c not in '?:!/;' )
'abc#@efg12'

使用re.sub正则表达式

从 Python 3.5 开始,可以使用正则表达式re.sub替换:

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

例子

import re
line = 'Q: Do I write ;/.??? No!!!'
re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)

'QDoIwriteNo'

解释

正则表达式(regex)中, | 是逻辑 OR 和\\转义空格和可能是实际正则表达式命令的特殊字符。 sub代表替换,在本例中为空字符串''

对于允许字符串中的某些字符的相反要求,您可以使用带有集合补码运算符[^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'

来自python 正则表达式文档

不在范围内的字符可以通过对集合进行补充来匹配。 如果集合的第一个字符是'^' ,则将匹配所有不在集合中的字符。 例如, [^5]将匹配除 '5' 之外的任何字符,而[^^]将匹配除'^'之外'^'任何字符。 如果^不是集合中的第一个字符,则没有特殊含义。

提问者几乎得到了它。 与 Python 中的大多数事情一样,答案比您想象的要简单。

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

您不必执行嵌套的 if/for 循环操作,但确实需要单独检查每个字符。

line = line.translate(None, " ?.!/;:")
>>> s = 'a1b2c3'
>>> ''.join(c for c in s if c not in '123')
'abc'

字符串在 Python 中是不可变的。 replace方法在替换后返回一个新字符串。 尝试:

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

这与您的原始代码相同,只是在循环内添加了对line的赋值。

请注意,字符串replace()方法会替换字符串中出现的所有字符,因此您可以通过对要删除的每个字符使用replace()来做得更好,而不是遍历字符串中的每个字符。

我很惊讶还没有人推荐使用内置过滤器功能。

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

    s = "1212edjaq"

假设我们要过滤掉所有不是数字的东西。 ]使用过滤器内置方法“...相当于生成器表达式(如果函数(项目)中的项目的项目)”[ Python 3 内置:]

    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"

我不确定过滤器在效率方面的排名如何,但知道在进行列表理解等时如何使用是一件好事。

更新

从逻辑上讲,由于过滤器有效,你也可以使用列表理解,从我读到的内容来看,它应该更有效,因为 lambda 是编程函数世界的华尔街对冲基金经理。 另一个优点是它是一种单线,不需要任何进口。 例如,使用上面定义的相同字符串 's',

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

就是这样。 返回将是原始字符串中所有数字字符的字符串。

如果您有可接受/不可接受字符的特定列表,则只需调整列表理解的“if”部分。

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

使用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.

以下是完成此任务的一些可能方法:

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”是西班牙语单词,表示 bat... 有趣的词,因为它包含所有元音 :)

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

因此,对于此特定输入,尝试 4 似乎是最快的。

这是我的 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)

试试这个:

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

此方法在 Python 3 中运行良好

您必须重新分配str变量:

for char in line:
if char in " ?.!/;:":
    line = line.replace(char,'')
#!/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

您还可以使用函数来使用列表替换不同类型的正则表达式或其他模式。 有了它,您可以混合正则表达式、字符类和真正基本的文本模式。 当您需要替换很多元素(如 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 = ["[!@#$]", "%"]
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

我使用的方法可能不会那么有效,但它非常简单。 我可以使用切片和格式一次删除不同位置的多个字符。 下面是一个例子:

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

这将导致 'removed' 保留单词 'this'。

格式化对于在打印字符串中途打印变量非常有帮助。 它可以使用%后跟变量的数据类型插入任何数据类型; 所有数据类型都可以使用%s ,浮点数(又名小数)和整数可以使用%d

切片可用于对字符串进行复杂的控制。 当我输入words[:3] 时,它允许我选择字符串中从开头(冒号在数字之前,这意味着“从开头到”)到第 4 个字符(包括第 4 个)的所有字符特点)。 3 等于第 4 位的原因是因为 Python 从 0 开始。然后,当我输入word[-1:] 时,它表示最后的第二个字符(冒号在数字后面)。 输入 -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 开始计数,因此您也需要这样做。

这个怎么样:

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

在 Python 3.5 中

例如,

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

从字符串中删除所有数字

>>> # Character stripping
>>> a = '?abcd1234!!'
>>> t.lstrip('?')
'abcd1234!!'
>>> t.strip('?!')
'abcd1234'

您可以使用 re 模块的正则表达式替换。 使用 ^ 表达式可以让您从字符串中准确选择您想要的内容。

    import re
    text = "This is absurd!"
    text = re.sub("[^a-zA-Z]","",text) # Keeps only Alphabets
    print(text)

对此的输出将是“Thisisabsurd”。 只有在 ^ 符号后指定的内容才会出现。

字符串方法replace不会修改原始字符串。 它保留原件并返回修改后的副本。

你想要的是这样的: line = line.replace(char,'')

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

但是,每次删除一个字符时都创建一个新字符串是非常低效的。 我建议改为:

def replace_all(line, baddies, *):
    """
    The following is documentation on how to use the class,
    without reference to the implementation details:

    For implementation notes, please see comments begining with `#`
    in the source file.

    [*crickets chirp*]

    """

    is_bad = lambda ch, baddies=baddies: return ch in baddies
    filter_baddies = lambda ch, *, is_bad=is_bad: "" if is_bad(ch) else ch
    mahp = replace_all.map(filter_baddies, line)
    return replace_all.join('', join(mahp))

    # -------------------------------------------------
    # WHY `baddies=baddies`?!?
    #     `is_bad=is_bad`
    # -------------------------------------------------
    # Default arguments to a lambda function are evaluated
    # at the same time as when a lambda function is
    # **defined**.
    #
    # global variables of a lambda function
    # are evaluated when the lambda function is
    # **called**
    #
    # The following prints "as yellow as snow"
    #
    #     fleece_color = "white"
    #     little_lamb = lambda end: return "as " + fleece_color + end
    #
    #     # sometime later...
    #
    #     fleece_color = "yellow"
    #     print(little_lamb(" as snow"))
    # --------------------------------------------------
replace_all.map = map
replace_all.join = str.join

如果您希望您的字符串只允许使用 ASCII 码的字符,您可以使用这段代码:

for char in s:
    if ord(char) < 96 or ord(char) > 123:
        s = s.replace(char, "")

它将删除 a....z 之外的所有字符,甚至是大写。

下面一个..不使用正则表达式概念..

ipstring ="text with symbols!@#$^&*( ends here"
opstring=''
for i in ipstring:
    if i.isalnum()==1 or i==' ':
        opstring+=i
    pass
print opstring

即使下面的方法也有效

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

输出: abcde

我正在尝试使用Python从字符串中删除特定字符。 这是我现在正在使用的代码。 不幸的是,它似乎对字符串没有任何作用。

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

如何正确执行此操作?

递归拆分: s=string ; 字符=要删除的字符

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!

# 对于目录中的每个文件,重命名文件名

   file_list = os.listdir (r"D:\Dev\Python")

   for file_name in file_list:

       os.rename(file_name, re.sub(r'\d+','',file_name))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM