在Python中将字符串转换为所有小写字母以去除所有非ASCII字母字符的最有效方法是什么?

发布于 2021-01-29 18:20:33

我有一个简单的任务需要在Python中执行,该任务是将字符串转换为所有小写字母,并去除所有非ASCII非字母字符。

例如:

"This is a Test" -> "thisisatest"
"A235th@#$&( er Ra{}|?>ndom" -> "atherrandom"

我有一个简单的功能可以做到这一点:

import string
import sys

def strip_string_to_lowercase(s):
    tmpStr = s.lower().strip()
    retStrList = []
    for x in tmpStr:
        if x in string.ascii_lowercase:
            retStrList.append(x)

    return ''.join(retStrList)

但是我不禁想到有一种更有效或更优雅的方法。

谢谢!


编辑:

感谢所有回答。我学会了,并且在某些情况下重新学习了很多python。

关注者
0
被浏览
154
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    另一个解决方案(不是pythonic,但速度非常快)是使用string.translate-
    尽管请注意,这不适用于unicode。还值得注意的是,您可以通过将字符移动到集合(通过哈希查找,而不是每次都执行线性搜索)中来加快Dana的代码。以下是我给出的各种解决方案的时间安排:

    import string, re, timeit
    
    # Precomputed values (for str_join_set and translate)
    
    letter_set = frozenset(string.ascii_lowercase + string.ascii_uppercase)
    tab = string.maketrans(string.ascii_lowercase + string.ascii_uppercase,
                           string.ascii_lowercase * 2)
    deletions = ''.join(ch for ch in map(chr,range(256)) if ch not in letter_set)
    
    s="A235th@#$&( er Ra{}|?>ndom"
    
    # From unwind's filter approach
    def test_filter(s):
        return filter(lambda x: x in string.ascii_lowercase, s.lower())
    
    # using set instead (and contains)
    def test_filter_set(s):
        return filter(letter_set.__contains__, s).lower()
    
    # Tomalak's solution
    def test_regex(s):
        return re.sub('[^a-z]', '', s.lower())
    
    # Dana's
    def test_str_join(s):
        return ''.join(c for c in s.lower() if c in string.ascii_lowercase)
    
    # Modified to use a set.
    def test_str_join_set(s):
        return ''.join(c for c in s.lower() if c in letter_set)
    
    # Translate approach.
    def test_translate(s):
        return string.translate(s, tab, deletions)
    
    
    for test in sorted(globals()):
        if test.startswith("test_"):
            assert globals()[test](s)=='atherrandom'
            print "%30s : %s" % (test, timeit.Timer("f(s)", 
                  "from __main__ import %s as f, s" % test).timeit(200000))
    

    这给了我:

                   test_filter : 2.57138351271
               test_filter_set : 0.981806765698
                    test_regex : 3.10069885233
                 test_str_join : 2.87172979743
             test_str_join_set : 2.43197956381
                test_translate : 0.335367566218
    

    [编辑]还更新了过滤器解决方案。(请注意,set.__contains__此处使用的区别很大,因为它避免了对lambda进行额外的函数调用。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看