在 Python 中从字符串中删除除字母数字字符之外的所有内容

2025-01-06 08:32:00
admin
原创
94
摘要:问题描述:使用 Python 从字符串中删除所有非字母数字字符的最佳方法是什么?该问题的 PHP 版本中给出的解决方案可能只需进行一些细微调整即可,但对我而言似乎不太“Python化”。为了记录,我不只是想去掉句号和逗号(和其他标点符号),还想去掉引号、括号等。解决方案 1:我只是出于好奇而对一些函数进行了计...

问题描述:

使用 Python 从字符串中删除所有非字母数字字符的最佳方法是什么?

该问题的 PHP 版本中给出的解决方案可能只需进行一些细微调整即可,但对我而言似乎不太“Python化”。

为了记录,我不只是想去掉句号和逗号(和其他标点符号),还想去掉引号、括号等。


解决方案 1:

我只是出于好奇而对一些函数进行了计时。在这些测试中,我从字符串中删除了非字母数字字符string.printable(内置string模块的一部分)。发现使用编译的'[W_]+'pattern.sub('', str)是最快的。

$ python -m timeit -s \n     "import string" \n     "''.join(ch for ch in string.printable if ch.isalnum())" 
10000 loops, best of 3: 57.6 usec per loop

$ python -m timeit -s \n    "import string" \n    "filter(str.isalnum, string.printable)"                 
10000 loops, best of 3: 37.9 usec per loop

$ python -m timeit -s \n    "import re, string" \n    "re.sub('[W_]', '', string.printable)"
10000 loops, best of 3: 27.5 usec per loop

$ python -m timeit -s \n    "import re, string" \n    "re.sub('[W_]+', '', string.printable)"                
100000 loops, best of 3: 15 usec per loop

$ python -m timeit -s \n    "import re, string; pattern = re.compile('[W_]+')" \n    "pattern.sub('', string.printable)" 
100000 loops, best of 3: 11.2 usec per loop

解决方案 2:

正则表达式来解决这个问题:

import re
re.sub(r'W+', '', your_string)

根据 Python 定义'W== [^a-zA-Z0-9_],它排除所有numbersletters并且_

解决方案 3:

使用str.translate()方法。

假设你经常这样做:

  1. 一次创建一个包含所有想要删除的字符的字符串:

delchars = ''.join(c for c in map(chr, range(256)) if not c.isalnum())
  1. 每当你想要压缩一个字符串时:

scrunched = s.translate(None, delchars)

设置成本可能与相比更具优势re.compile;边际成本要低得多:

C:junk>python26python -mtimeit -s"import string;d=''.join(c for c in map(chr,range(256)) if not c.isalnum());s=string.printable" "s.translate(None,d)"
100000 loops, best of 3: 2.04 usec per loop

C:junk>python26python -mtimeit -s"import re,string;s=string.printable;r=re.compile(r'[W_]+')" "r.sub('',s)"
100000 loops, best of 3: 7.34 usec per loop

注意:用作string.printable基准数据会给模式带来'[W_]+'不公平的优势;所有非字母数字字符都在一堆中......在典型数据中需要进行多次替换:

C:junk>python26python -c "import string; s = string.printable; print len(s),repr(s)"
100 '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;=>?@[\\]^_`{|}~     

x0bx0c'

re.sub如果你多做一些工作,就会出现以下结果:

C:junk>python26python -mtimeit -s"d=''.join(c for c in map(chr,range(256)) if not c.isalnum());s='foo-'*25" "s.translate(None,d)"
1000000 loops, best of 3: 1.97 usec per loop

C:junk>python26python -mtimeit -s"import re;s='foo-'*25;r=re.compile(r'[W_]+')" "r.sub('',s)"
10000 loops, best of 3: 26.4 usec per loop

解决方案 4:

您可以尝试:

print ''.join(ch for ch in some_string if ch.isalnum())

解决方案 5:

>>> import re
>>> string = "Kl13@£$%[};'\""
>>> pattern = re.compile('W')
>>> string = re.sub(pattern, '', string)
>>> print string
Kl13

解决方案 6:

怎么样:

def ExtractAlphanumeric(InputString):
    from string import ascii_letters, digits
    return "".join([ch for ch in InputString if ch in (ascii_letters + digits)])

它的工作原理是使用列表推导来生成字符列表(InputString如果它们存在于组合ascii_lettersdigits字符串中)。然后将列表连接成一个字符串。

解决方案 7:

我使用perfplot (我的一个项目)检查了结果,发现

pattern = re.compile("[W_]")
pattern.sub("", s)

是最快的。对于短字符串,

"".join(filter(str.isalnum, s))

也是可以接受的。

在此处输入图片描述

重现情节的代码:

import perfplot
import random
import re
import string

pattern = re.compile("[W_]")
pattern_plus = re.compile("[W_]+")


def setup(n):
    return "".join(random.choices(string.ascii_letters + string.digits, k=n))


def string_alphanum(s):
    return "".join(ch for ch in s if ch.isalnum())


def filter_str(s):
    return "".join(filter(str.isalnum, s))


def re_sub(s):
    return re.sub("[W_]", "", s)


def re_sub_pattern(s):
    return pattern.sub("", s)


def re_sub_plus(s):
    return re.sub("[W_]+", "", s)


def re_sub_pattern_plus(s):
    return pattern_plus.sub("", s)


b = perfplot.bench(
    setup=setup,
    kernels=[
        string_alphanum,
        filter_str,
        re_sub,
        re_sub_pattern,
        re_sub_plus,
        re_sub_pattern_plus,
    ],
    n_range=[2**k for k in range(15)],
)
b.save("out.png")
b.show()

解决方案 8:

sent = "".join(e for e in sent if e.isalpha())

解决方案 9:

作为此处其他答案的衍生,我提供了一种非常简单且灵活的方法来定义您想要限制字符串内容的一组字符。在这种情况下,我允许字母数字加上破折号和下划线。只需PERMITTED_CHARS根据您的用例添加或删除字符即可。

PERMITTED_CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-" 
someString = "".join(c for c in someString if c in PERMITTED_CHARS)

解决方案 10:

使用可打印的 ASCII 随机字符串进行计时:

from inspect import getsource
from random import sample
import re
from string import printable
from timeit import timeit

pattern_single = re.compile(r'[W]')
pattern_repeat = re.compile(r'[W]+')
translation_tb = str.maketrans('', '', ''.join(c for c in map(chr, range(256)) if not c.isalnum()))


def generate_test_string(length):
    return ''.join(sample(printable, length))


def main():
    for i in range(0, 60, 10):
        for test in [
            lambda: ''.join(c for c in generate_test_string(i) if c.isalnum()),
            lambda: ''.join(filter(str.isalnum, generate_test_string(i))),
            lambda: re.sub(r'[W]', '', generate_test_string(i)),
            lambda: re.sub(r'[W]+', '', generate_test_string(i)),
            lambda: pattern_single.sub('', generate_test_string(i)),
            lambda: pattern_repeat.sub('', generate_test_string(i)),
            lambda: generate_test_string(i).translate(translation_tb),

        ]:
            print(timeit(test), i, getsource(test).lstrip('            lambda: ').rstrip(',
'), sep='    ')


if __name__ == '__main__':
    main()

结果(Python 3.7):

       Time       Length                           Code                           
6.3716264850008880  00  ''.join(c for c in generate_test_string(i) if c.isalnum())
5.7285426190064750  00  ''.join(filter(str.isalnum, generate_test_string(i)))
8.1875841680011940  00  re.sub(r'[W]', '', generate_test_string(i))
8.0002205439959650  00  re.sub(r'[W]+', '', generate_test_string(i))
5.5290945199958510  00  pattern_single.sub('', generate_test_string(i))
5.4417179649972240  00  pattern_repeat.sub('', generate_test_string(i))
4.6772285089973590  00  generate_test_string(i).translate(translation_tb)
23.574712151996210  10  ''.join(c for c in generate_test_string(i) if c.isalnum())
22.829975890002970  10  ''.join(filter(str.isalnum, generate_test_string(i)))
27.210196289997840  10  re.sub(r'[W]', '', generate_test_string(i))
27.203713296003116  10  re.sub(r'[W]+', '', generate_test_string(i))
24.008979928999906  10  pattern_single.sub('', generate_test_string(i))
23.945240008994006  10  pattern_repeat.sub('', generate_test_string(i))
21.830899796994345  10  generate_test_string(i).translate(translation_tb)
38.731336012999236  20  ''.join(c for c in generate_test_string(i) if c.isalnum())
37.942474347000825  20  ''.join(filter(str.isalnum, generate_test_string(i)))
42.169366310001350  20  re.sub(r'[W]', '', generate_test_string(i))
41.933375883003464  20  re.sub(r'[W]+', '', generate_test_string(i))
38.899814646996674  20  pattern_single.sub('', generate_test_string(i))
38.636144253003295  20  pattern_repeat.sub('', generate_test_string(i))
36.201238164998360  20  generate_test_string(i).translate(translation_tb)
49.377356811004574  30  ''.join(c for c in generate_test_string(i) if c.isalnum())
48.408927293996385  30  ''.join(filter(str.isalnum, generate_test_string(i)))
53.901889764994850  30  re.sub(r'[W]', '', generate_test_string(i))
52.130339455994545  30  re.sub(r'[W]+', '', generate_test_string(i))
50.061149017004940  30  pattern_single.sub('', generate_test_string(i))
49.366573111998150  30  pattern_repeat.sub('', generate_test_string(i))
46.649754120997386  30  generate_test_string(i).translate(translation_tb)
63.107938601999194  40  ''.join(c for c in generate_test_string(i) if c.isalnum())
65.116287978999030  40  ''.join(filter(str.isalnum, generate_test_string(i)))
71.477421126997800  40  re.sub(r'[W]', '', generate_test_string(i))
66.027950693998720  40  re.sub(r'[W]+', '', generate_test_string(i))
63.315361931003280  40  pattern_single.sub('', generate_test_string(i))
62.342320287003530  40  pattern_repeat.sub('', generate_test_string(i))
58.249303059004890  40  generate_test_string(i).translate(translation_tb)
73.810345625002810  50  ''.join(c for c in generate_test_string(i) if c.isalnum())
72.593953348005020  50  ''.join(filter(str.isalnum, generate_test_string(i)))
76.048324580995540  50  re.sub(r'[W]', '', generate_test_string(i))
75.106637657001560  50  re.sub(r'[W]+', '', generate_test_string(i))
74.681338128997600  50  pattern_single.sub('', generate_test_string(i))
72.430461594005460  50  pattern_repeat.sub('', generate_test_string(i))
69.394243567003290  50  generate_test_string(i).translate(translation_tb)

str.maketrans&str.translate速度最快,但包含所有非 ASCII 字符。
re.compile&pattern.sub速度较慢,但​​比''.join&快filter

解决方案 11:

对于简单的单行代码(Python 3.0):

''.join(filter( lambda x: x in '0123456789abcdefghijklmnopqrstuvwxyz', the_string_you_want_stripped ))

对于 Python <3.0:

filter( lambda x: x in '0123456789abcdefghijklmnopqrstuvwxyz', the_string_you_want_stripped )

注意:如果需要,您可以将其他字符添加到允许的字符列表中(例如“0123456789abcdefghijklmnopqrstuvwxyz.,_”)。

解决方案 12:

Python 3

使用与@John Machin 的答案相同的方法,但针对 Python 3 进行了更新:

  • 更大的字符集

  • 对工作方式稍作改变translate

现在假定 Python 代码采用 UTF-8 编码

(来源:PEP 3120)

这意味着包含所有要删除的字符的字符串会变得更大1:

    
del_chars = ''.join(c for c in map(chr, range(1114111)) if not c.isalnum())
    

现在该translate方法需要使用一个翻译表,我们可以用以下命令创建该表maketrans()

    
del_map = str.maketrans('', '', del_chars)
    

现在,和以前一样,任何s你想“压缩”的字符串:

    
scrunched = s.translate(del_map)
    

使用来自@Joe Machin 的最后一个计时示例,我们可以看到它仍然re以一个数量级的速度跳动:

    
> python -mtimeit -s"d=''.join(c for c in map(chr,range(1114111)) if not c.isalnum());m=str.maketrans('','',d);s='foo-'*25" "s.translate(m)"
    
1000000 loops, best of 5: 255 nsec per loop
    
> python -mtimeit -s"import re;s='foo-'*25;r=re.compile(r'[W_]+')" "r.sub('',s)"
    
50000 loops, best of 5: 4.8 usec per loop
    

1为什么是 1,114,111?Python 文档页面解释道:Unicode 字符串是代码点序列,这些代码点是从 0 到 0x10FFFF(十进制为 1,114,111)的数字。相关文档部分

解决方案 13:

for char in my_string:
    if not char.isalnum():
        my_string = my_string.replace(char,"")

解决方案 14:

一个简单的解决方案,因为这里的所有答案都很复杂

filtered = ''
for c in unfiltered:
    if str.isalnum(c):
        filtered += c
    
print(filtered)

解决方案 15:

例如,如果您想要保留像 áéíóúãẽĩõũ 这样的字符,请使用以下命令:

import re
re.sub('[Wd_]+', '', your_string)

解决方案 16:

如果我理解正确的话,最简单的方法是使用正则表达式,因为它为您提供了很大的灵活性,但另一种简单的方法是使用for循环,下面是带有示例的代码,我还计算了单词的出现次数并将其存储在字典中。

s = """An... essay is, generally, a piece of writing that gives the author's own 
argument — but the definition is vague, 
overlapping with those of a paper, an article, a pamphlet, and a short story. Essays 
have traditionally been 
sub-classified as formal and informal. Formal essays are characterized by "serious 
purpose, dignity, logical 
organization, length," whereas the informal essay is characterized by "the personal 
element (self-revelation, 
individual tastes and experiences, confidential manner), humor, graceful style, 
rambling structure, unconventionality 
or novelty of theme," etc.[1]"""

d = {}      # creating empty dic      
words = s.split() # spliting string and stroing in list
for word in words:
    new_word = ''
    for c in word:
        if c.isalnum(): # checking if indiviual chr is alphanumeric or not
            new_word = new_word + c
    print(new_word, end=' ')
    # if new_word not in d:
    #     d[new_word] = 1
    # else:
    #     d[new_word] = d[new_word] +1
print(d)

如果这个答案有用,请评分!

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用