代码之家  ›  专栏  ›  技术社区  ›  Stefan Falk

如何对元组列表进行分组?

  •  2
  • Stefan Falk  · 技术社区  · 7 年前

    注释 :当然,我知道如何在显式for循环中实现这一点,但我正在寻找一个更具可读性的解决方案。

    如果可能的话,我想用一些内置的功能来解决这个问题。最好的情况是

    result = [ *groupby logic* ]
    

    import numpy as np
    np.random.seed(42)
    
    N = 10
    
    my_tuples = list(zip(np.random.choice(list('ABC'), size=N),
                         np.random.choice(range(100), size=N)))
    

    哪里 my_tuples

    [('C', 74),
     ('A', 74),
     ('C', 87),
     ('C', 99),
     ('A', 23),
     ('A', 2),
     ('C', 21),
     ('B', 52),
     ('C', 1),
     ('C', 87)]
    

    如何使用标签a、b和c对索引(每个元组的索引1处的整数值)进行分组 groupby 来自Itertools?

    如果我这样做:

    from itertools import groupby
    
    #..
    
    [(k,*v) for k, v in dict(groupby(my_tuples, lambda x: x[0])).items()]
    

    我知道这会带来错误的结果。

    期望的结果应该是

    {
      'A': [74, 23, 2],
      # ..
    }
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   jpp    7 年前

    你应该用 collections.defaultdict 为了一个O( n )解决方案,请参阅 @PatrickHaugh's answer .

    使用 itertools.groupby 分组前需要排序,导致( n 日志 n )复杂性:

    from itertools import groupby
    from operator import itemgetter
    
    sorter = sorted(my_tuples, key=itemgetter(0))
    grouper = groupby(sorter, key=itemgetter(0))
    
    res = {k: list(map(itemgetter(1), v)) for k, v in grouper}
    
    print(res)
    
    {'A': [74, 23, 2],
     'B': [52],
     'C': [74, 87, 99, 21, 1, 87]}
    
        2
  •  4
  •   Patrick Haugh    7 年前

    最简单的解决方法可能是不使用 groupby 完全。

    from collections import defaultdict
    
    d = defaultdict(list)
    
    for k, v in my_tuples:
        d[k].append(v)
    

    我不使用的原因 子句 是因为 groupby(iterable) 将项目分组 iterable 相邻的。为了得到所有 'C' 值加在一起,您首先必须对列表进行排序。除非你有理由 子句 ,没必要。