for char in line:
if char in " ?.!/;:":
line.replace(char,'')
我该如何正确地做这件事?
请参见为什么调用字符串方法(例如.replace或.strip)不会修改(变异)字符串?以获取有关此方法存在何种问题的特定调试问题。这里的答案主要集中在如何解决问题上。
for char in line:
if char in " ?.!/;:":
line.replace(char,'')
我该如何正确地做这件事?
请参见为什么调用字符串方法(例如.replace或.strip)不会修改(变异)字符串?以获取有关此方法存在何种问题的特定调试问题。这里的答案主要集中在如何解决问题上。
line.replace(...)
的效果只是创建一个新的字符串,而不是更改旧的字符串。您需要将其重新绑定(分配)给line
,以使该变量获取新值,并删除那些字符。str.translate
,(请参见下面的Python 3答案):line = line.translate(None, '!@#$')
或使用 re.sub
进行正则表达式替换。
import re
line = re.sub('[!@#$]', '', line)
line
中属于该类的任何字符都将被替换为sub
方法的第二个参数:一个空字符串。
在Python 3中,字符串是Unicode编码的。您需要进行一些不同的翻译。kevpie在其中一个答案的comment中提到了这一点,在str.translate
的文档中也有说明。
当调用Unicode字符串的translate
方法时,您不能像上面那样传递第二个参数。您也不能将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 '!@#$'})
或者,就像Joseph Lee提出的那样,使用str.maketrans
创建相同的翻译表:
unicode_line = unicode_line.translate(str.maketrans('', '', '!@#$'))
* 为了与早期版本的Python兼容,您可以创建一个“空”翻译表来替换None
:
import string
line = line.translate(string.maketrans('', ''), '!@#$')
string.maketrans
创建了一个“翻译表”,它只是一个包含0到255的字符序号值的字符串。line.translate
只接受一个参数,第一个解决方案行不通。 - marczoidline.translate({ord(i):None for i in '!@#$'})
。 - naveen"'"
即可设置该字符。 - intuitednotes = notes.translate({ord(i):None for i in '\"\''})
。 - RyanGunicode_line.translate(str.maketrans('','','!@#$'))
或unicode_line.translate(dict.fromkeys(map(ord, '!@#$')))
. - Martijn Pieters我是否理解有误,还是只是以下内容让我感到困惑:
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,"")
- elgehelgeb
中所有字符放入一个set中,初始化一个空列表,然后迭代a
,如果当前字符不在set中,则将其添加到列表中。完成后,您可以将列表转换回字符串。线性时间和线性(额外)空间。 - kebab-caselen(string)
。 - DonCarleone>>> 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)
。 - user3064538re.sub
正则表达式自Python 3.5以来,可以使用正则表达式re.sub
进行替换:
import re
re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)
import re
line = 'Q: Do I write ;/.??? No!!!'
re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)
'QDoIwriteNo'
在正则表达式中,|
表示逻辑或,\
用于转义可能是实际正则表达式命令的空格和特殊字符。而sub
代表替换(substitution),在这种情况下是用空字符串''
进行替换。
re.sub()
中的第一个字符串替换为 '\ |\?|\.|\!|\/|\;|\:|\n|\r'
。 - 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'
不在某一范围内的字符可以通过对该范围取反来匹配。如果集合的第一个字符是
'^'
,那么所有不在集合中的字符都将被匹配。例如,[^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()
而不是循环遍历字符串中的每个字符来更好地处理。
line
的每个字符,并检查该字符是否在要删除的字符集中。如果是,则删除line
中所有其出现的情况,那么为什么要继续遍历line
的其余字符并再次检查已经不可能存在的字符?相反,我建议使用以下代码:for char in " ?.!/;:": line = line.replace(char, "")
这将有与要删除的字符数一样多的迭代次数。更易读的版本在此处 - pfabri我很惊讶没有人推荐使用内置的filter函数。
import operator
import string # only for the example you could use a custom string
s = "1212edjaq"
假设我们想要过滤掉非数字的内容。使用filter内置方法"…相当于生成器表达式(item for item in iterable if function(item))" [Python 3内置函数:Filter]
sList = list(s)
intsList = list(string.digits)
obj = filter(lambda x: operator.contains(intsList, x), sList)))
>> <filter object @ hex>
nums = "".join(list(obj))
print(nums)
>> "1212"
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])
lambda
,那么使用 operator.contains
没有任何意义。应该将 lambda x: operator.contains(intsList, x)
改为 lambda x: x in intsList
,或者如果你想要获得 C 级别的检查,可以直接使用 intsList.__contains__
(完全不需要 lambda
)。 - ShadowRanger
filter
函数和Lambda表达式:filter(lambda ch: ch not in " ?.!/;:", line)
。我认为这非常简洁高效。当然,它会返回一个新的字符串,你需要给它分配一个变量名。 - John Red