繁体   English   中英

是否有Pythonic方法使这种逻辑更优雅?

[英]Is there a Pythonic way to make this logic more elegant?

我是Python的新手,我一直在玩它来完成简单的任务。 我有一堆CSV需要以复杂的方式操作,但我为了学习Python而将其分解为更小的任务。

现在,给定一个字符串列表,我想删除字符串中任何名称的用户定义的标题前缀。 包含名称的任何字符串将包含名称,带有或不带标题前缀。 我有以下,它有效,但它感觉不必要的复杂。 是否有更多的Pythonic方法来做到这一点? 谢谢!

# Return new list without title prefixes for strings in a list of strings.
def strip_titles(line, title_prefixes):
    new_csv_line = []
    for item in line:
        for title_prefix in title_prefixes:
            if item.startswith(title_prefix):
                new_csv_line.append(item[len(title_prefix)+1:])
                break
            else:
                if title_prefix == title_prefixes[len(title_prefixes)-1]:
                    new_csv_line.append(item)
                else:
                    continue
    return new_csv_line

if __name__ == "__main__":
    test_csv_line = ['Mr. Richard Stallman', 'I like cake', 'Mrs. Margaret Thatcher', 'Jean-Claude Van Damme']
    test_prefixes = ['Mr.', 'Ms.', 'Mrs.']
    print strip_titles(test_csv_line, test_prefixes)
[re.sub(r'^(Mr|Ms|Mrs)\.\s+', '', s) for s in test_csv_line]

假设prefixes是可变的,可能是本地化的一个方面,或者你不想因为其他原因而不使用正则表达式,你可以做这样的事情(未经测试的代码):

def strip_title(string, prefixes):
    for prefix in prefixes:
         if string.startswith(prefix + ' '):
             return string[len(prefix) + 1:]
    return string

stripped = (list(strip_title(cell, prefixes) for cell in line)
            for line in lines)

这不是特别有效,因为算法最终会进行大量冗余检查(例如,如果线以M开头则检查三次)。 这种事情是使用正则表达式的一个重要原因。

或者,您可以通过转义每个前缀并使用|连接它们来动态构建正则表达式 分支:

def TitleStripper(prefixes):
    import re
    escaped_titles = (re.escape(prefix) for prefix in prefixes)
    prefix_re = re.compile('^({0}) '.format('|'.join(escaped_titles)))
    def strip_title(string):
        return prefix_re.sub('', string, 1)
    return strip_title

TitleStripper函数创建一个闭包函数strip_title ,它与前一个函数strip_title ,但是是为一组特定的前缀而构建的。 调用strip_title = TitleStripper(prefixes)您可以调用strip_title(string)

主要是由于使用正则表达式,这将比第一种方法快一点,可能以牺牲清晰度为代价。

如果你真的只需要检查三个前缀,那么这些方法中的任何一个都是过度的,你应该使用另一个答案中解释的静态RE。

一个更Pythonic的方法是用else:子句替换“end of list”检查到for item in line: loop中的for item in line: 如果for循环完成而没有被中断,则执行else

# Return new list without title prefixes for strings in a list of strings.    
def strip_titles(line, title_prefixes):
    new_csv_line = []
    for item in line:
        for title_prefix in title_prefixes:
            if item.startswith(title_prefix):
                new_csv_line.append(item[len(title_prefix)+1:])
                break
        else:
            new_csv_line.append(item)
    return new_csv_line

逻辑与你的逻辑相同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM