Mat*_*ips 491 python string immutability
我正在尝试使用Python从字符串中删除特定字符.这是我现在正在使用的代码.不幸的是它似乎对字符串没有任何作用.
for char in line:
if char in " ?.!/;:":
line.replace(char,'')
Run Code Online (Sandbox Code Playgroud)
我该怎么做呢?
int*_*ted 589
Python中的字符串是不可变的(不能更改).因此,效果line.replace(...)只是创建一个新的字符串,而不是改变旧的字符串.您需要重新绑定(赋值)它以line使该变量获取新值,并删除这些字符.
而且,你这样做的方式相对较慢.对于经验丰富的pythonator来说,这也可能有点令人困惑,他们会看到一个双重嵌套的结构,并想一想更复杂的事情正在发生.
从Python 2.6和更新的Python 2.x版本*开始,您可以使用str.translate,(但请继续阅读Python 3的差异):
line = line.translate(None, '!@#$')
Run Code Online (Sandbox Code Playgroud)
或正则表达式替换 re.sub
import re
line = re.sub('[!@#$]', '', line)
Run Code Online (Sandbox Code Playgroud)
括号中的字符构成一个字符类.line该类中的任何字符都将替换为第二个参数sub:空字符串.
在Python 3中,字符串是Unicode.你将不得不翻译一点点.kevpie 在其中一个答案的评论中提到了这一点,并在文档中str.translate注明了.
调用translateUnicode字符串的方法时,您无法传递我们上面使用的第二个参数.您也不能None作为第一个参数传递,甚至不能传递string.maketrans.相反,您将字典作为唯一参数传递.这个字典将字符的序数值(即调用ord它们的结果)映射到应该替换它们的字符的序数值,或者对我们有用None- 表示它们应该被删除.
所以要用Unicode字符串做上面的舞蹈,你会称之为
translation_table = dict.fromkeys(map(ord, '!@#$'), None)
unicode_line = unicode_line.translate(translation_table)
Run Code Online (Sandbox Code Playgroud)
这里dict.fromkeys和map习惯于简洁地生成包含的字典
{ord('!'): None, ord('@'): None, ...}
Run Code Online (Sandbox Code Playgroud)
更简单,正如另一个答案所说,创建字典:
unicode_line = unicode_line.translate({ord(c): None for c in '!@#$'})
Run Code Online (Sandbox Code Playgroud)
*为了与早期的Pythons兼容,您可以创建一个"null"转换表来代替None:
import string
line = line.translate(string.maketrans('', ''), '!@#$')
Run Code Online (Sandbox Code Playgroud)
这里string.maketrans用于创建转换表,它只是一个包含序号值为0到255的字符的字符串.
gsb*_*bil 207
我在这里忽略了这一点,还是仅仅是以下内容:
string = "ab1cd1ef"
string.replace("1","")
print string
# result: "abcdef"
Run Code Online (Sandbox Code Playgroud)
把它放在一个循环中:
a = "a!b@c#d$"
b = "!@#$"
for char in b:
a = a.replace(char,"")
print a
# result: "abcd"
Run Code Online (Sandbox Code Playgroud)
gho*_*g74 42
>>> line = "abc#@!?efg12;:?"
>>> ''.join( c for c in line if c not in '?:!/;' )
'abc#@efg12'
Run Code Online (Sandbox Code Playgroud)
Ser*_*ndt 28
re.sub在Python 3.5中易于使用re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)
Run Code Online (Sandbox Code Playgroud)
>>> import re
>>> line = 'Q: Do I write ;/.??? No!!!'
>>> re.sub('\ |\?|\.|\!|\/|\;|\:', '', line)
'QDoIwriteNo'
Run Code Online (Sandbox Code Playgroud)
在正则表达式(正则表达式)中,|是一个逻辑OR并\转义空格和特殊字符,它们可能是实际的正则表达式命令.sub代表替代.
cod*_*k3y 19
对于仅允许字符串中的某些字符的反向要求,可以使用带有set complement运算符的正则表达式[^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'
Run Code Online (Sandbox Code Playgroud)
可以通过补充该组来匹配不在范围内的字符.如果该组的第一个字符是
'^',则将匹配该组中不存在的所有字符.例如,[^5]将匹配除"5"之外的任何字符,并[^^]匹配除了之外的任何字符'^'.^如果它不是集合中的第一个字符,则没有特殊含义.
mgo*_*old 18
提问者几乎拥有它.像Python中的大多数东西一样,答案比你想象的要简单.
>>> line = "H E?.LL!/;O:: "
>>> for char in ' ?.!/;:':
... line = line.replace(char,'')
...
>>> print line
HELLO
Run Code Online (Sandbox Code Playgroud)
您不必执行嵌套的if/for循环操作,但您需要单独检查每个字符.
Muh*_*uri 14
line = line.translate(None, " ?.!/;:")
Run Code Online (Sandbox Code Playgroud)
eat*_*kin 10
>>> s = 'a1b2c3'
>>> ''.join(c for c in s if c not in '123')
'abc'
Run Code Online (Sandbox Code Playgroud)
字符串在Python中是不可变的.该replace方法在替换后返回一个新字符串.尝试:
for char in line:
if char in " ?.!/;:":
line = line.replace(char,'')
Run Code Online (Sandbox Code Playgroud)
小智 9
试试这个:
def rm_char(original_str, need2rm):
''' Remove charecters in "need2rm" from "original_str" '''
return original_str.translate(str.maketrans('','',need2rm))
Run Code Online (Sandbox Code Playgroud)
该方法在Python 3中运行良好
我很惊讶没有人建议使用内置过滤器功能.
import operator
import string # only for the example you could use a custom string
s = "1212edjaq"
Run Code Online (Sandbox Code Playgroud)
假设我们要过滤掉所有不是数字的东西.使用filter builtin方法"...相当于生成器表达式(如果函数(item),则迭代中的项目项目)"[ Python 3 Builtins:Filter ]
sList = list(s)
intsList = list(string.digits)
obj = filter(lambda x: operator.contains(intsList, x), sList)))
Run Code Online (Sandbox Code Playgroud)
在Python 3中,这将返回
>> <filter object @ hex>
Run Code Online (Sandbox Code Playgroud)
要获得打印的字符串,
nums = "".join(list(obj))
print(nums)
>> "1212"
Run Code Online (Sandbox Code Playgroud)
我不确定过滤器在效率方面是如何排名的,但是在做列表推导等时知道如何使用它是一件好事.
UPDATE
从逻辑上讲,由于过滤器的工作原理,你也可以使用列表理解,从我所读到的它应该更有效率,因为lambdas是编程功能世界的华尔街对冲基金经理.另一个优点是它是一个不需要任何进口的单线程.例如,使用上面定义的相同字符串's',
num = "".join([i for i in s if i.isdigit()])
Run Code Online (Sandbox Code Playgroud)
而已.返回将是原始字符串中所有字符的字符串.
如果您有可接受/不可接受字符的特定列表,则只需调整列表理解的"if"部分.
target_chars = "".join([i for i in s if i in some_list])
Run Code Online (Sandbox Code Playgroud)
或者,
target_chars = "".join([i for i in s if i not in some_list])
Run Code Online (Sandbox Code Playgroud)
使用filter,你只需要一行
line = filter(lambda char: char not in " ?.!/;:", line)
Run Code Online (Sandbox Code Playgroud)
这会将字符串视为可迭代的,并在lambda返回时检查每个字符True:
Run Code Online (Sandbox Code Playgroud)>>> 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"))
Run Code Online (Sandbox Code Playgroud)
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))
Run Code Online (Sandbox Code Playgroud)
在我的盒子里你会得到:
attempt1 2.2334518376057244
attempt2 1.8806643818474513
attempt3 7.214925774955572
attempt4 1.7271184513757465
Run Code Online (Sandbox Code Playgroud)
所以看来尝试4对于这个特定的输入来说是最快的。
| 归档时间: |
|
| 查看次数: |
1244518 次 |
| 最近记录: |