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

时间:2010-10-15 03:46:21

标签: python string immutability

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

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

我该如何正确地做到这一点?

29 个答案:

答案 0 :(得分:547)

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

另外,你这样做的方式相对而言会变慢。对于经验丰富的蟒蛇人来说,这也有点令人困惑,他们会看到一个双重嵌套的结构,并想一想更复杂的事情。

从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中,字符串是Unicode。你将不得不翻译一点点。 kevpie在其中一个答案的comment中提到了这一点,并在documentation for str.translate中注明了。

调用Unicode字符串的translate方法时,无法传递上面使用的第二个参数。您也无法将None作为第一个参数传递,甚至也不能传递string.maketrans的转换表。相反,您将字典作为唯一参数传递。这个字典将字符的序数值(即调用ord的结果)映射到应该替换它们的字符的序数值,或者对我们有用 - {{1表示应删除它们。

所以要使用Unicode字符串进行上述舞蹈,你会称之为

None

此处dict.fromkeysmap用于简洁地生成包含

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

更简单,如another answer puts it,创建字典:

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

*为了与早期的Pythons兼容,您可以创建一个“null”转换表来代替unicode_line = unicode_line.translate({ord(c): None for c in '!@#$'})

None

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

答案 1 :(得分:187)

我在这里忽略了这一点,还是仅仅是以下几点:

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

把它放在一个循环中:

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

答案 2 :(得分:39)

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

答案 3 :(得分:22)

在Python 3.5

中轻松获得re.sub
re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)

实施例

>>> import re

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

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

解释

regular expressions(正则表达式)中,|是逻辑OR,\转义空格和特殊字符,可能是实际的正则表达式命令。 sub代表替代。

答案 4 :(得分:19)

对于字符串中允许某些字符的反向要求,您可以使用带有set complement operator [^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'

来自the python regular expression documentation

  

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

答案 5 :(得分:18)

提问者几乎拥有它。像Python中的大多数东西一样,答案比你想象的要简单。

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

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

答案 6 :(得分:14)

line = line.translate(None, " ?.!/;:")

答案 7 :(得分:10)

$(document).ready(function(){
  $('.up').click(function() {
    var clicks = parseInt($(this).parent().find('.clicks').html());
    clicks = clicks +1

    if(clicks == 10) {
        $(this).hide();
    }
    
    $(this).parent().find('.clicks').html(clicks);
  });
  
  $('.down').click(function() {
    var clicks = parseInt($(this).parent().find('.clicks').html());
    if(clicks > 0) {
        clicks = clicks - 1
    }

    if(clicks < 10) {
       $(this).parent().find('.up').show()
    }
    
    $(this).parent().find('.clicks').html(clicks);
  });
});

答案 8 :(得分:8)

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

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

答案 9 :(得分:6)

我很惊讶没有人建议使用内置的过滤器功能。

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

    s = "1212edjaq"

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

    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"

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

更新

从逻辑上讲,由于过滤器的工作原理,你也可以使用列表理解,从我所看到的它应该更有效率,因为lambdas是编程功能世界的华尔街对冲基金经理。另一个优点是它是一个不需要任何进口的单线程。例如,使用上面定义的相同字符串'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])

答案 10 :(得分:6)

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

答案 11 :(得分:4)

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

"Usage: r2 -i '.!r2snow'" -- This should be documented, since it's not that obvious.

PS:示例中使用元音...而不是使用“?。!/ ;:”,是的,“ murcielago”是西班牙语中用来说蝙蝠的单词...有趣的词,因为它包含所有元音:)< / p>

PS2:如果您对性能感兴趣,可以使用以下简单代码来衡量这些尝试:

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

在我的框中,您会得到:

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

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

答案 12 :(得分:3)

这是我的Python 2/3兼容版本。由于翻译api已经改变。

nav{position: relative;}
nav ul {
  list-style: none;
  margin:0;
  padding: 0;
}
li.has_children{
  position:relative;
}
li.has_children > ul{
  transition: all 0.3s ease 0s;
  visibility:hidden;
  margin-top:-10px;
  opacity:0;
  background-color: green;
}
li.has_children:hover > ul{
  margin-top:0px;
  visibility:visible;
  opacity:1;
}
nav > div > ul> li > ul > li > ul{
  position:absolute;
  top:0;
  left:100%;
  /* You may want to add a width */
}
nav > div > ul > li {
  float: left;
}
nav >div> ul > li  > a:hover{
  background-color: red;
}

答案 13 :(得分:3)

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

答案 14 :(得分:1)

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

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

这将导致“删除”&#39;坚持这个&#39;这个&#39;。

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

切片可用于对字符串进行复杂控制。当我输入单词[:3] 时,它允许我从头开始选择字符串中的所有字符(冒号在数字之前,这将意味着&#39;从开始到&# 39;)到第4个字符(包括第4个字符)。原因3等于直到第4位是因为Python从0开始。然后,当我把 word [-1:] 时,它意味着结尾的第二个最后一个字符(冒号在数字后面) )。使用-1将使Python从最后一个字符开始计数,而不是第一个字符。同样,Python将从0开始。因此, word [-1:] 基本上意味着从第二个最后一个字符到字符串结尾。

因此,通过在我想要删除的角色之前切掉角色并将角色夹在一起之后,我可以删除不需要的角色。 把它想象成一个香肠。在中间它很脏,所以我想摆脱它。我只是切断了我想要的两端,然后把它们放在一起,中间没有不需要的部分。

如果我想删除多个连续的字符,我只需在[](切片部分)中移动数字。或者如果我想从不同的位置删除多个字符,我可以简单地将多个切片夹在一起。

示例:

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

已删除等于&#39;很酷&#39;。

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

已删除等于&#39; macs&#39;。

在这种情况下, [3:5] 表示位置 3中的字符到位置 5处的字符(不包括最终字符)位置)。

请记住, Python从0 开始计数,因此您也需要这样做。

答案 15 :(得分:1)

您还可以使用函数来使用列表替换不同类型的正则表达式或其他模式。有了它,您可以混合正则表达式,字符类和真正基本的文本模式。当你需要替换像HTML这样的很多元素时,这非常有用。

* NB:适用于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

答案 16 :(得分:1)

这个怎么样:

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

答案 17 :(得分:1)

#!/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

答案 18 :(得分:1)

您必须重新分配str变量:

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

答案 19 :(得分:0)

如果您希望通过使用ASCII代码将字符串仅允许使用字符,则可以使用以下代码:

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

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

答案 20 :(得分:0)

字符串方法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

答案 21 :(得分:0)

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

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

   for file_name in file_list:

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

答案 22 :(得分:0)

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

n+1

输出为“ Thisisabsurd”。仅显示在^符号后指定的内容。

答案 23 :(得分:0)

递归拆分: s = string; chars = chars to remove

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!

答案 24 :(得分:0)

试试这个:

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

此方法在python 3.5.2

中运行良好

答案 25 :(得分:0)

你可以使用set

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

答案 26 :(得分:0)

即使是以下方法也适用

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

输出&gt;&gt; ABCDE

答案 27 :(得分:0)

在Python 3.5中

如,

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

删除字符串中的所有数字

答案 28 :(得分:0)

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

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