【问题标题】:Is there a better way to split of objects by one of its attributes?有没有更好的方法通过对象的属性之一来拆分对象?
【发布时间】:2013-10-06 16:25:22
【问题描述】:

我目前正在开发一个 AppEngine 应用程序,并且有一个来自数据存储区的对象列表,我想根据它们的属性之一将它们分成组。我有一个解决方案,但我想检查是否有人知道更好的方法。

这是我目前拥有的代码:

for report in reports:
  if report.status == 'new':
    new_reports.append(report)
  elif report.status == 'read':
    read_reports.append(report)
  elif report.status == 'accepted':
    accepted_reports.append(report)
  elif report.status == 'deined':
    denied_reports.append(report)
  elif report.status == 'resubmitted':
    resubmitted_reports.append(report)

欢迎任何想法!

【问题讨论】:

    标签: python list google-app-engine sorting python-2.7


    【解决方案1】:

    你可以有一个从状态到功能的字典:

    d= {"new":new_reports.append,
        "read":read_reports.append,
        "accepted":accepted_reports.append,
        "deined":denied_reports.append,
        "resubmitted":resubmitted_reports.append
    }
    
    for report in reports:
         d[report.status](report)
    

    【讨论】:

    • 我有点喜欢这个——很好地提醒了方法对象是如何被绑定的。
    • @Thomas 我喜欢这个,因为我来自 java ;)
    【解决方案2】:

    字典会更好,而不是所有的局部变量:

    reports_by_status = {'new': [],
         'read': [],
         'accepted': [],
         'deined': [],    # denied?
         'resubmitted': []}
    
    for report in reports:
        d[report.status].append(report)
    

    但是你打错了!通过使用 status 变量中的任何数据来分配类别可能会很好地防止这种情况:

    reports_by_status = {}
    for report in reports:
        if report.status not in reports_by_status:
            reports_by_status[status] = []
        reports_by_status[status].append(report)
    

    这是一种常见的模式,所以我们有一些方法可以让它变得更好:

    reports_by_status = {}
    for report in reports:
        reports_by_status.set_default(report.status, []).append(report)
    

    但更好的是默认字典:

    from collections import defaultdict
    by_status = defaultdict(list)
    for report in reports:
        by_status[report].append(report)
    

    itertools.groupby很好,它封装了分类动作:

    from itertools import groupby
    by_status = {}
    for category, group in groupby(reports, lambda x: x.status):
        by_status[category] = list(group)
    

    但现在我们的循环正在寻找map()-ish,所以让我们使用列表推导:

    from itertools import groupby
    dict([(k:list(v)) for k, v in groupby(reports, lambda x: x.status)])
    

    然后记住我们在 Python 2.7 中,所以我们也有字典推导:

    from itertools import groupby
    {k:list(v) for k, v in groupby(reports, lambda x: x.status)}
    

    还是我目前最喜欢的,

    from itertools import groupby
    from operator import attrgetter
    {k:list(v) for k, v in groupby(reports, attrgetter('status'))}
    

    【讨论】:

      【解决方案3】:

      字典呢:

      dct = {"new":new_reports, "read":read_reports, "accepted":accepted_reports, "denied":denied_reports, "resubmitted":resubmitted_reports}
      for report in reports:
          dct[report.status].append(report)
      

      或者,如果 report.status 可能不在字典中,您可以添加一个 try/except 块:

      dct = {"new":new_reports, "read":read_reports,"accepted":accepted_reports, "denied":denied_reports, "resubmitted":resubmitted_reports}
      for report in reports:
          try:
              dct[report.status].append(report)
          except KeyError:
              continue
      

      【讨论】:

        猜你喜欢
        • 2011-05-26
        • 2020-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多