【问题标题】:How to group an array by multiple keys?如何通过多个键对数组进行分组?
【发布时间】:2015-11-04 11:34:52
【问题描述】:

我想要一个函数,它可以根据所有字典共有的任意键集将字典列表分组为字典子列表。

例如,我希望根据一组键将以下列表分组到字典的子列表中

l = [{'name':'b','type':'new','color':'blue','amount':100},{'name':'c','type':'new','color':'red','amount':100},{'name':'d','type':'old','color':'gold','amount':100},{'name':'e','type':'old','color':'red','amount':100},
{'name':'f','type':'old','color':'red','amount':100},{'name':'g','type':'normal','color':'red','amount':100}]

如果我想按类型分组,将产生以下列表,其中有一个子列表,其中每个子列表具有相同的类型:

[[{'name':'b','type':'new','color':'blue','amount':100},{'name':'c','type':'new','color':'red','amount':100}],[{'name':'d','type':'old','color':'gold','amount':100},{'name':'e','type':'old','color':'red','amount':100},
{'name':'f','type':'old','color':'red','amount':100}],[{'name':'g','type':'normal','color':'red','amount':100}]]

如果我想按类型和颜色进行分组,如果列表包含具有相同类型和颜色的子列表,则会出现以下结果:

[[{'name':'b','type':'new','color':'blue','amount':100}],[{'name':'c','type':'new','color':'red','amount':100}],[{'name':'d','type':'old','color':'gold','amount':100}],[{'name':'e','type':'old','color':'red','amount':100},
{'name':'f','type':'old','color':'red','amount':100}],[{'name':'g','type':'normal','color':'red','amount':100}]]

我了解以下功能可以一键分组,但我想多键分组:

 def group_by_key(l,i):

      l = [list(grp) for key, grp in itertools.groupby(sorted(l, key=operator.itemgetter(i)), key=operator.itemgetter(i))]

这是我使用上面的 group_by_function 的尝试

 def group_by_multiple_keys(l,*keys):
      for key in keys:
          l = group_by_key(l,key)
          l = [item for sublist in l for item in sublist]
      return l 

问题在于它在按键分组后立即取消分组。相反,我想用另一个键重新组合它,并且仍然有一个子列表列表。

【问题讨论】:

    标签: python arrays dictionary


    【解决方案1】:

    itertools.groupby() + operator.itemgetter() 会做你想做的事。 groupby() 接受一个可迭代对象和一个键函数,并通过将每个项目传递给键函数返回的值对可迭代对象中的项目进行分组。 itemgetter() 是一个工厂,它返回一个函数,该函数从传递给它的任何项目中获取指定项目。

    from __future__ import print_function
    
    import pprint
    
    from itertools import groupby
    from operator import itemgetter
    
    
    def group_by_keys(iterable, keys):
        key_func = itemgetter(*keys)
    
        # For groupby() to do what we want, the iterable needs to be sorted
        # by the same key function that we're grouping by.
        sorted_iterable = sorted(iterable, key=key_func)
    
        return [list(group) for key, group in groupby(sorted_iterable, key_func)]
    
    
    dicts = [
        {'name': 'b', 'type': 'new', 'color': 'blue', 'amount': 100},
        {'name': 'c', 'type': 'new', 'color': 'red', 'amount': 100},
        {'name': 'd', 'type': 'old', 'color': 'gold', 'amount': 100},
        {'name': 'e', 'type': 'old', 'color': 'red', 'amount': 100},
        {'name': 'f', 'type': 'old', 'color': 'red', 'amount': 100},
        {'name': 'g', 'type': 'normal', 'color': 'red', 'amount': 100}
        ]
    

    例子:

    >>> pprint.pprint(group_by_keys(dicts, ('type',)))
    [[{'amount': 100, 'color': 'blue', 'name': 'b', 'type': 'new'},
      {'amount': 100, 'color': 'red', 'name': 'c', 'type': 'new'}],
     [{'amount': 100, 'color': 'gold', 'name': 'd', 'type': 'old'},
      {'amount': 100, 'color': 'red', 'name': 'e', 'type': 'old'},
      {'amount': 100, 'color': 'red', 'name': 'f', 'type': 'old'}],
     [{'amount': 100, 'color': 'red', 'name': 'g', 'type': 'normal'}]]
    >>> 
    >>> pprint.pprint(group_by_keys(dicts, ('type', 'color')))
    [[{'amount': 100, 'color': 'blue', 'name': 'b', 'type': 'new'}],
     [{'amount': 100, 'color': 'red', 'name': 'c', 'type': 'new'}],
     [{'amount': 100, 'color': 'gold', 'name': 'd', 'type': 'old'}],
     [{'amount': 100, 'color': 'red', 'name': 'e', 'type': 'old'},
      {'amount': 100, 'color': 'red', 'name': 'f', 'type': 'old'}],
     [{'amount': 100, 'color': 'red', 'name': 'g', 'type': 'normal'}]]
    

    【讨论】:

      猜你喜欢
      • 2018-02-20
      • 2022-01-11
      • 1970-01-01
      • 2020-10-21
      • 1970-01-01
      • 2022-11-14
      • 2021-12-24
      • 2019-10-09
      • 2016-04-30
      相关资源
      最近更新 更多