【问题标题】:Splitting a list of dictionaries into several lists of dictionaries将字典列表拆分为多个字典列表
【发布时间】:2011-05-04 17:59:36
【问题描述】:

我一直在努力解决这个问题,但无济于事......任何帮助都会非常有用 赞赏。

我有:

[{'event': 0, 'voltage': 1, 'time': 0},
{'event': 0, 'voltage': 2, 'time': 1},
{'event': 1, 'voltage': 1, 'time': 2},
{'event': 1, 'voltage': 2, 'time': 3},
{'event': 2, 'voltage': 1, 'time': 4},
{'event': 2, 'voltage': 2, 'time': 5},
...]

我想像这样将字典列表拆分为每个事件(可以有任意多个事件):

list0 = [{'event': 0, 'voltage': 1, 'time': 0},
{'event': 0, 'voltage': 2, 'time': 1}]

list1 = [{'event': 1, 'voltage': 1, 'time': 2},
{'event': 1, 'voltage': 2, 'time': 3}]

list2 = [{'event': 2, 'voltage': 1, 'time': 4},
{'event': 2, 'voltage': 2, 'time': 5}]

listN = ...

【问题讨论】:

    标签: python list dictionary split


    【解决方案1】:

    在我看来,一个简单的实现就足够了:

    grouping = {}    
    for d in dictlist:
        if d[field] not in grouping:
            grouping[d[field]] = []
        grouping[d[field]].append(d)
    result = list(result.values())
    

    【讨论】:

      【解决方案2】:

      使用defaultdict

      import collections
      
      result = collections.defaultdict(list)
      
      for d in dict_list:
          result[d['event']].append(d)
      
      result_list = result.values()        # Python 2.x
      result_list = list(result.values())  # Python 3
      

      这样,您不必对有多少不同的事件或是否缺少任何事件做出任何假设。

      这会为您提供一个列表列表。如果您想要一个按事件索引的dict,如果您打算进行任何随机访问,我可能会使用dict(d)

      就构建一堆单独的列表而言,我认为这是个坏主意。这将需要将它们创建为全局变量或使用 eval(或以其他方式变得 hacky),除非您确切知道将有多少您声称不知道。最好将它们保存在容器中。

      【讨论】:

        【解决方案3】:

        这个是O(n log n),因为排序,但我不会太担心,除非列表中有很多项。

        如果列表已经按事件排序,当然可以跳过排序。

        >>> from operator import itemgetter
        >>> from itertools import groupby
        >>> d=[{'event': 0, 'voltage': 1, 'time': 0},
        ... {'event': 0, 'voltage': 2, 'time': 1},
        ... {'event': 1, 'voltage': 1, 'time': 2},
        ... {'event': 1, 'voltage': 2, 'time': 3},
        ... {'event': 2, 'voltage': 1, 'time': 4},
        ... {'event': 2, 'voltage': 2, 'time': 5}]
        >>> groupby(sorted(d, key=itemgetter('event')), key=itemgetter('event'))
        <itertools.groupby object at 0xb78138c4>
        >>> for x in _:
        ...   print x[0], list(x[1])
        ... 
        0 [{'time': 0, 'event': 0, 'voltage': 1}, {'time': 1, 'event': 0, 'voltage': 2}]
        1 [{'time': 2, 'event': 1, 'voltage': 1}, {'time': 3, 'event': 1, 'voltage': 2}]
        2 [{'time': 4, 'event': 2, 'voltage': 1}, {'time': 5, 'event': 2, 'voltage': 2}]
        

        【讨论】:

          【解决方案4】:

          我认为你真正想要的是过滤它们:

          elist = [{'event': 0, 'voltage': 1, 'time': 0},
          {'event': 0, 'voltage': 2, 'time': 1},
          {'event': 1, 'voltage': 1, 'time': 2},
          {'event': 1, 'voltage': 2, 'time': 3},
          {'event': 2, 'voltage': 1, 'time': 4},
          {'event': 2, 'voltage': 2, 'time': 5}]
          
          
          from itertools import ifilter
          
          def get_events(elist, n):
              return ifilter( lambda d: d['event'] == n , elist)
          
          for e in get_events(elist,0):
              print e
          

          此解决方案不会创建额外的结构。 (想想巨大的事件列表)

          另一个非常好的解决方案是使用 groupby:

          from itertools import groupby
          from operator import itemgetter
          for group in groupby(elist, itemgetter('event')):
              id, event_list = group
              for e in event_list:
                  print e
          
          {'time': 0, 'event': 0, 'voltage': 1}
          {'time': 1, 'event': 0, 'voltage': 2}
          {'time': 2, 'event': 1, 'voltage': 1}
          {'time': 3, 'event': 1, 'voltage': 2}
          {'time': 4, 'event': 2, 'voltage': 1}
          {'time': 5, 'event': 2, 'voltage': 2}
          

          【讨论】:

            【解决方案5】:
            dict_list = [{'event': 0, 'voltage': 1, 'time': 0},
            {'event': 0, 'voltage': 2, 'time': 1},
            {'event': 1, 'voltage': 1, 'time': 2},
            {'event': 1, 'voltage': 2, 'time': 3},
            {'event': 2, 'voltage': 1, 'time': 4},
            {'event': 2, 'voltage': 2, 'time': 5},
            ]
            
            import collections
            dol = collections.defaultdict(list)
            for d in dict_list:
               k = d["event"]
               dol[k].append(d)
            
            print dol
            

            如果您知道“事件”键是连续的从零开始的整数,则可以使用列表代替,但额外的复杂性可能不会为您带来任何好处。

            python 2.5 中添加了 defaultdict,但早期版本的解决方法并不难(参见 Nick D 的代码)。

            【讨论】:

              猜你喜欢
              • 2010-12-19
              • 2021-09-09
              • 2020-04-23
              • 2021-10-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多