使用 Python 从字符串中删除特定字符
- 2024-11-27 10:42:00
- admin 原创
- 16
问题描述:
我正在尝试使用 Python 从字符串中删除特定字符。这是我现在正在使用的代码。不幸的是,它似乎对字符串没有任何作用。
for char in line:
if char in " ?.!/;:":
line.replace(char,'')
我该如何正确地做到这一点?
有关此方法存在什么问题的具体调试问题,请参阅为什么调用字符串方法(例如 .replace 或 .strip)不会修改(变异)字符串? 。这里的答案主要关注如何解决问题。
解决方案 1:
Python 中的字符串是不可变的(无法更改)。因此,的效果line.replace(...)
只是创建一个新字符串,而不是更改旧字符串。您需要将其重新绑定(分配)为,line
以便让该变量采用新值,并删除那些字符。
此外,你这样做的方式相对来说会比较慢。对于经验丰富的 Python 程序员来说,这也可能有点令人困惑,他们看到双重嵌套结构时会认为其中有更复杂的事情。
从 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
中也提到了这一点。
调用 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 的字符的字符串。
解决方案 2:
我是不是错过了重点,还是只是以下几点:
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"
解决方案 3:
>>> line = "abc#@!?efg12;:?"
>>> ''.join( c for c in line if c not in '?:!/;' )
'abc#@efg12'
解决方案 4:
使用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)中,|
是逻辑或,并`转义可能为实际正则表达式命令的空格和特殊字符。而
sub代表**替换,**在本例中为空字符串
''`。
解决方案 5:
提问者几乎已经知道了。就像 Python 中的大多数东西一样,答案比你想象的要简单。
>>> line = "H E?.LL!/;O:: "
>>> for char in ' ?.!/;:':
... line = line.replace(char,'')
...
>>> print line
HELLO
您不必执行嵌套的 if/for 循环,但您确实需要单独检查每个字符。
解决方案 6:
对于仅允许字符串中某些字符的反向要求,可以使用带有集合补码运算符的正则表达式[^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”之外的任何字符,并将[^^]
匹配除 之外的任何字符
'^'
。^
如果它不是集合中的第一个字符,则没有特殊含义。
解决方案 7:
line = line.translate(None, " ?.!/;:")
解决方案 8:
>>> s = 'a1b2c3'
>>> ''.join(c for c in s if c not in '123')
'abc'
解决方案 9:
在 Python 中字符串是不可变的。该replace
方法在替换后返回一个新字符串。尝试:
for char in line:
if char in " ?.!/;:":
line = line.replace(char,'')
line
这与您的原始代码相同,但在循环内部添加了赋值。
请注意,字符串replace()
方法会替换字符串中出现的所有replace()
字符,因此,您可以通过对要删除的每个字符使用该方法,而不是循环遍历字符串中的每个字符,从而获得更好的效果。
解决方案 10:
尝试一下这个:
def rm_char(original_str, need2rm):
''' Remove charecters in "need2rm" from "original_str" '''
return original_str.translate(str.maketrans('','',need2rm))
此方法在 Python 3 中有效
解决方案 11:
令我惊讶的是,没有人推荐使用内置过滤功能。
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)))
在 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])
解决方案 12:
使用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.
解决方案 13:
以下是完成此任务的一些可能方法:
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"))
附言:示例中使用元音代替“ ?.!/;:”... 是的,“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
因此,对于这个特定的输入,似乎 attempt4 是最快的。
解决方案 14:
这是我的 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)
解决方案 15:
#!/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
解决方案 16:
您还可以使用函数,通过列表替换不同类型的正则表达式或其他模式。这样,您可以混合正则表达式、字符类和非常基本的文本模式。当您需要替换大量元素(如 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 和列表 notwanted 作为参数。对于元素或模式列表中的每个项目,如果需要替换,则会执行替换。
输出:
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
解决方案 17:
我使用的方法可能不太有效,但它非常简单。我可以使用切片和格式化一次性删除不同位置的多个字符。以下是示例:
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 开始计数,因此您也需要这样做。
解决方案 18:
在 Python 3.5 中
例如,
os.rename(file_name, file_name.translate({ord(c): None for c in '0123456789'}))
从字符串中删除所有数字
解决方案 19:
以下内容已在本帖中解释过。我只是将其汇总起来作为答案。
"".join(filter(lambda x: x not in " ?.!/;:", line))
解决方案 20:
这个怎么样:
def text_cleanup(text):
new = ""
for i in text:
if i not in " ?.!/;:":
new += i
return new
解决方案 21:
下面一个..没有使用正则表达式概念..
ipstring ="text with symbols!@#$^&*( ends here"
opstring=''
for i in ipstring:
if i.isalnum()==1 or i==' ':
opstring+=i
pass
print opstring
解决方案 22:
递归拆分:
s=字符串;chars=要删除的字符
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!
解决方案 23:
您可以使用 re 模块的正则表达式替换。使用 ^ 表达式可以让您从字符串中准确选择所需的内容。
import re
text = "This is absurd!"
text = re.sub("[^a-zA-Z]","",text) # Keeps only Alphabets
print(text)
输出结果为“Thisisabsurd”。只有 ^ 符号后指定的内容才会出现。
解决方案 24:
# 对于目录中的每个文件,重命名文件名
file_list = os.listdir (r"D:DevPython")
for file_name in file_list:
os.rename(file_name, re.sub(r'd+','',file_name))
解决方案 25:
即使下面的方法也有效
line = "a,b,c,d,e"
alpha = list(line)
while ',' in alpha:
alpha.remove(',')
finalString = ''.join(alpha)
print(finalString)
输出:abcde
解决方案 26:
string 方法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
解决方案 27:
如果您希望字符串仅包含使用 ASCII 代码的字符,则可以使用以下代码:
for char in s:
if ord(char) < 96 or ord(char) > 123:
s = s.replace(char, "")
它将删除除 a....z 之外的所有字符,甚至大写字母。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理必备:盘点2024年13款好用的项目管理软件