【问题标题】:Sort list of strings by substring using Python使用Python按子字符串对字符串列表进行排序
【发布时间】:2012-11-26 14:57:06
【问题描述】:

我有一个字符串列表,每个字符串都是格式几乎完全相同的电子邮件。每封电子邮件中都有很多信息,但最重要的信息是设施名称和事件日期。

我希望能够获取该电子邮件列表,并创建一个新列表,其中电子邮件根据“location_substring”分组在一起,然后再次为“incident_date_substring”排序,以便所有来自一个位置将按时间顺序在列表中组合在一起。

设施子字符串通常可以在每封电子邮件的主题行中找到。事件日期可以在电子邮件中以“事件日期:”开头的一行中找到。

关于我将如何做这件事的任何想法?

【问题讨论】:

  • 老实说,我是新手,不知道如何做到这一点。我认为我应该做的是定义一个从每个字符串中提取设施名称的函数。然后创建另一个提取日期的函数。然后使用 sorted() 方法,将它们作为键,或其他东西......但我真的不知道!
  • python 中常用的一种叫做 decorate-sort-undecorate 的成语。见here
  • 你知道什么是正则表达式吗? (不意味着冒犯,如果你不知道它是什么,谷歌一个很好的 tut。)因为它是你问题的解决方案。首先使用正则表达式搜索位置并构建一个字典,其中位置作为键,电子邮件列表作为值。
  • 我知道什么是正则表达式。我实际上有一个字典,其中设施的名称作为值,设施 ID 作为键,我从放在一起的文本文件中提取。这样做的目的是为了程序中的后续步骤。听起来你是在建议我创建一个新的,但我没有考虑过。
  • @mrpryd:如果您发布示例电子邮件,我会看看是否可以为您准备一些基本代码。

标签: python string list sorting substring


【解决方案1】:

编写一个函数,从每封电子邮件中返回您关心的两条信息:

def email_sort_key(email):
    """Find two pieces of info in the email, and return them as a tuple."""
    # ...search, search...
    return "location", "incident_date"

然后,将该函数用作排序的键:

emails.sort(key=email_sort_key)

排序键函数应用于所有值,并根据键函数返回的值对值重新排序。在这种情况下,key 函数返回一个元组。元组按字典顺序排列:找到第一个不相等的元素,然后在比较不相等的元素时比较元组。

【讨论】:

  • 好的,这就是我之前在 cmets 中讨论的内容。问题是,这个功能是什么样的?它需要正则表达式吗?
  • @mrpryd 这个问题是关于对列表进行排序,还是关于从每封电子邮件中可靠地提取相关信息?
  • 两者,有点:P 最终目标是对列表进行排序。但要这样做,您必须事先从列表的每个元素中提取信息。在这一点上,我确信 Regex 是一种方式……基于我上面发布的虚假电子邮件示例。那么这个答案就可以了
【解决方案2】:

您的解决方案可能如下所示:

def getLocation (mail): pass
    #magic happens here

def getDate (mail): pass
    #here be dragons

emails = [...] #original list

#Group mails by location
d = {}
for mail in emails:
    loc = getLocation (mail)
    if loc not in d: d [loc] = []
    d [loc].append (mail)

#Sort mails inside each group by date
for k, v in d.items ():
    d [k] = sorted (v, key = getDate)

【讨论】:

    【解决方案3】:

    这是你可以做的:

    from collections import defaultdict
    from datetime import datetime
    import re
    
    mails = ['list', 'of', 'emails']
    
    mails2 = defaultdict(list)
    
    for mail in mails:
        loc = re.search(r'Subject:.*?for\s(.+?)\n', mail).group(1)
        mails2[loc].append(mail)
    
    for m in mails2.values():
        m.sort(key=lambda x:datetime.strptime(re.search(r'Date of Incident:\s(.+?)\n',
                                                        x).group(1), '%m/%d/%Y'))
    

    请注意,对于正则表达式不匹配的情况,这绝对没有错误处理。

    【讨论】:

    • 我最终不必做所有这些,但正则表达式显然是继续提取名称和日期的方法。我可能会继续使用发布的其他一些答案,因为它更简单——但你的正则表达式模式让我可以轻松地提取信息。你能解释更多关于你是如何将模式组合在一起的吗?我能够使用 re.compile(r'Date of Incident:.*?(\d\d.\d\d.\d\d\d\d)') 来编码事件日期,这很相似你做了什么。但我还是不太明白每一个片段。希望正则表达式更简单!必须重新标记这个问题...
    猜你喜欢
    • 2020-03-07
    • 2021-10-13
    • 2021-06-10
    • 2018-05-20
    • 1970-01-01
    • 2013-04-15
    • 1970-01-01
    • 2018-07-02
    • 2012-10-14
    相关资源
    最近更新 更多