Answers:
Python中的字符串是不可变的(无法更改)。因此,的效果line.replace(...)
只是创建一个新字符串,而不是更改旧字符串。您需要重新绑定(分配)它line
,以使该变量采用新值,并删除这些字符。
而且,相对而言,您的操作方式会比较缓慢。这也可能会使经验丰富的pythonator感到有些困惑,他们将看到双重嵌套的结构,并暂时认为会发生一些更复杂的事情。
从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在对其中一个答案的评论中提到了这一点,并在的文档中str.translate
对此进行了注明。
当调用translate
Unicode字符串的方法时,您不能传递上面使用的第二个参数。您也不能None
作为第一个参数传递。相反,您将翻译表(通常是字典)作为唯一参数传递。此表将字符的序号值(即调用ord
它们的结果)映射到应替换它们的字符的序号值,或者(对我们有用)None
表示应删除它们。
因此,使用Unicode字符串进行上述舞蹈时,您会调用类似
translation_table = dict.fromkeys(map(ord, '!@#$'), 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 '!@#$'})
或使用创建相同的翻译表str.maketrans
:
unicode_line = unicode_line.translate(str.maketrans('', '', '!@#$'))
*为了与早期的Python兼容,您可以创建一个“空”转换表来代替None
:
import string
line = line.translate(string.maketrans('', ''), '!@#$')
这string.maketrans
是用来创建转换表的,它只是一个字符串,其中包含序号为0到255的字符。
line.translate
仅接受一个参数,第一个解决方案将不起作用
line.translate({ord(i):None for i in '!@#$'})
"'"
字符集即可。
notes = notes.translate({ord(i):None for i in '\"\''})
unicode_line.translate(str.maketrans('', '', '!@#$'))
。或unicode_line.translate(dict.fromkeys(map(ord, '!@#$')))
我是否在这里遗漏了要点,或者只是以下内容:
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"
for char in b: a=a.replace(char,"")
string=string.replace("1","")
代替。您在示例的循环部分中对此进行了说明,但是大多数人直到对这样一个简单的问题先弄一点代码后,才会对您的答案有那么深入的了解。
>>> line = "abc#@!?efg12;:?"
>>> ''.join( c for c in line if c not in '?:!/;' )
'abc#@efg12'
blacklist = set('?:!/;')
然后''.join(c for c in line if c not in blacklist)
re.sub
从Python 3.5开始具有正则表达式re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)
>>> import re
>>> line = 'Q: Do I write ;/.??? No!!!'
>>> re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)
'QDoIwriteNo'
在正则表达式(regex)中,|
它是逻辑OR,并\
转义可能是实际regex命令的空格和特殊字符。而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'
可以通过补充集合来匹配不在范围内的字符。如果集合的第一个字符是
'^'
,则所有不在集合中的字符都将被匹配。例如,[^5]
将匹配除“ 5”以外的任何字符,并将匹配除以外的[^^]
任何字符'^'
。^
如果不是集合中的第一个字符,则没有特殊含义。
询问者几乎拥有了它。像Python中的大多数事物一样,答案比您想象的要简单。
>>> line = "H E?.LL!/;O:: "
>>> for char in ' ?.!/;:':
... line = line.replace(char,'')
...
>>> print line
HELLO
您不必执行嵌套的if / for循环操作,但是您需要单独检查每个字符。
line = line.translate(None, " ?.!/;:")
字符串在Python中是不可变的。replace
替换后,该方法返回一个新字符串。尝试:
for char in line:
if char in " ?.!/;:":
line = line.replace(char,'')
line
。
令我惊讶的是,还没有人建议使用内置过滤器功能。
import operator
import string # only for the example you could use a custom string
s = "1212edjaq"
假设我们要过滤掉所有不是数字的内容。使用过滤器内置方法“ ...等效于生成器表达式(如果函数(item),则为可迭代的项目项)” [ 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])
operator.contains
,如果您使用的是lambda
反正。lambda x: operator.contains(intsList, x)
应该是拼写的lambda x: x in intsList
,或者如果您尝试获得C级检查,intsList.__contains__
(一点也不lambda
)可以解决问题。
使用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”是西班牙语中用来说蝙蝠的单词...有趣的词,因为它包含所有元音
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是最快的尝试。
list
,attempt1
并且"aeiou"
为了简单起见,可以将其重写为元组(删除[
并且]
将变成一个生成器,而无需创建列表)。您可以在中创建大量的一次性中介字符串attemt2
,attempt3
并且可以r'[aeiou]'
在一处使用regex的多个应用程序。每个人都有缺点-它很高兴看到不同的方式做事情,但请解决这些问题是很好的尝试,以及
这是我的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)
dict.fromkeys(map(ord, '!@#$'))
用来创建地图。
str.maketrans('', '', chars)
处理ord
转换和dict
构造(更不用说在意图上更明显了,因为它是与配对设计的str.translate
)。
#!/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
'
字符串。docs.python.org/2/library/re.html
这个怎么样:
def text_cleanup(text):
new = ""
for i in text:
if i not in " ?.!/;:":
new += i
return new
您还可以使用一个函数,以使用列表替换其他种类的正则表达式或其他模式。这样,您就可以混合使用正则表达式,字符类和真正的基本文本模式。当您需要替换许多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:])
这将导致“删除”中带有“ this”一词。
格式化对于在打印字符串中途打印变量非常有用。它可以使用%插入任何数据类型,后跟变量的数据类型。所有数据类型都可以使用%s,而浮点数(也就是小数)和整数可以使用%d。
切片可用于对字符串的复杂控制。当我输入words [:3]时,它允许我从字符串的开头选择所有字符(冒号在数字之前,这意味着“从开头到”)到第四个字符(包括第四个字符)字符)。之所以3等于第4位是因为Python从0开始。然后,当我将word [-1:]放到最后时,倒数第二个字符(冒号在数字后面)。放置-1将使Python从最后一个字符开始计数,而不是从第一个字符开始计数。同样,Python将从0开始。因此,单词[-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开始计数,因此您也需要这样做。
您可以使用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
>>> # Character stripping
>>> a = '?abcd1234!!'
>>> t.lstrip('?')
'abcd1234!!'
>>> t.strip('?!')
'abcd1234'
filter
函数和Lambda表达式:filter(lambda ch: ch not in " ?.!/;:", line)
。我认为也非常简洁高效。当然,它将返回一个新字符串,您必须为其分配一个名称。