从字符串中删除小写子字符串的快速方法?
Posted
技术标签:
【中文标题】从字符串中删除小写子字符串的快速方法?【英文标题】:fast way to remove lowercase substrings from string? 【发布时间】:2013-03-04 11:21:52 【问题描述】:在 Python 中(普通或使用 numpy)从字符串 s
中删除所有小写子字符串的有效方法是什么?
s = "FOObarFOOObBAR"
remove_lower(s) => "FOOFOOBAR"
【问题讨论】:
【参考方案1】:Python3.x 答案:
你可以制作一个字符串翻译表。创建转换表后,您可以重复使用它:
>>> import string
>>> table = str.maketrans('', '', string.ascii_lowercase)
>>> s = 'FOObarFOOObBAR'
>>> s.translate(table)
'FOOFOOOBAR'
以这种方式使用时,第一个参数值映射到第二个参数值(如果存在)。如果不存在,则假定为恒等映射。第三个参数是要移除的值的集合。
任何关心的人的旧 python2.x 答案:
我会使用str.translate
。如果您为翻译表传递None
,则仅执行删除步骤。在这种情况下,我将ascii_lowercase
作为要删除的字母传递。
>>> import string
>>> s = 'FOObarFOOObBAR'
>>> s.translate(None, string.ascii_lowercase)
'FOOFOOOBAR'
我怀疑你会找到更快的方法,但如果有人有动力,总有timeit
比较不同的选择:)。
【讨论】:
字符串模块不是已经弃用了吗? @DiegoHerranz -- 似乎不是。在reference docs 上搜索“depr”并没有出现任何结果。我认为这是一个普遍的谣言,因为其中的大多数方法只是内置str
类型的别名,因此它们将来可能会被弃用。
我认为不推荐使用的是(函数版本的)方法。例如,在 python 3.3 中,只有 ascii_lowercase
和 punctuation
这样的常量以及 Formatter
和 Template
这样的类。没有rindex
或split
。
啊,大概就是这样 :-)
这仅适用于字节字符串。如果字符串 s
是 unicode,则上面的代码将失败并显示 TypeError: translate() takes exactly one argument (2 given)
。由于字符串在 Python 3 中默认为 unicode,因此这在 Python 3 中不起作用。【参考方案2】:
我的第一个方法是''.join(x for x in s if not x.islower())
如果您需要速度,请使用 mgilson 答案,它会快很多。
>>> timeit.timeit("''.join(x for x in 'FOOBarBaz' if not x.islower())")
3.318969964981079
>>> timeit.timeit("'FOOBarBaz'.translate(None, string.ascii_lowercase)", "import string")
0.5369198322296143
>>> timeit.timeit("re.sub('[a-z]', '', 'FOOBarBaz')", "import re")
3.631659984588623
>>> timeit.timeit("r.sub('', 'FOOBarBaz')", "import re; r = re.compile('[a-z]')")
1.9642360210418701
>>> timeit.timeit("''.join(x for x in 'FOOBarBaz' if x not in lowercase)", "lowercase = set('abcdefghijklmnopqrstuvwxyz')")
2.9605889320373535
【讨论】:
+1 对当前的两个答案,但我更喜欢这个有两个原因。 #1 是我一直使用 genexps,所以我不必考虑语法。我永远不记得translate
和maketrans
是如何工作的。 #2 是这种方法更稳健:如果需求稍有变化,则更有可能存活。
@DSM -- 我也很难记住translate
和maketrans
是如何工作的,但我已经习惯了。烦人的部分是直到python3.x才没有str.maketrans
,所以如果你真的想使用翻译表,你实际上需要import
字符串。
如果您创建一个小写字符的本地set
,看看性能如何变化可能会很有趣。然后你可以测试集合中的成员而不是查看x.islower()
。当然,除非您可以预先计算该集合,否则您可能一无所获。您不想在每次迭代时都这样做。为了加快大约 30% 的速度(根据我的经验——没有实际时间),您还可以使用 list-comp 代替生成器表达式。【参考方案3】:
import re
remove_lower = lambda text: re.sub('[a-z]', '', text)
s = "FOObarFOOObBAR"
s = remove_lower(s)
print(s)
【讨论】:
以上是关于从字符串中删除小写子字符串的快速方法?的主要内容,如果未能解决你的问题,请参考以下文章