在列表中对项目进行分组的Pythonic方法

在列表中对项目进行分组的Pythonic方法,python,list,dictionary,collections,Python,List,Dictionary,Collections,考虑一个目录: items = [ {'a': 1, 'b': 9, 'c': 8}, {'a': 1, 'b': 5, 'c': 4}, {'a': 2, 'b': 3, 'c': 1}, {'a': 2, 'b': 7, 'c': 9}, {'a': 3, 'b': 8, 'c': 2} ] 是否有一种pythonic方法可以通过a字段提取和分组这些项目,以便: result = { 1 : [{'b': 9, 'c': 8}, {'b':

考虑一个目录:

items = [
    {'a': 1, 'b': 9, 'c': 8},
    {'a': 1, 'b': 5, 'c': 4},
    {'a': 2, 'b': 3, 'c': 1},
    {'a': 2, 'b': 7, 'c': 9},
    {'a': 3, 'b': 8, 'c': 2}
]
是否有一种pythonic方法可以通过
a
字段提取和分组这些项目,以便:

result = {
    1 : [{'b': 9, 'c': 8}, {'b': 5, 'c': 4}]
    2 : [{'b': 3, 'c': 1}, {'b': 7, 'c': 9}]
    3 : [{'b': 8, 'c': 2}]
}
欢迎参考任何类似的Pythonic构造。

使用:

如果项目未按排序顺序排列,则您可以对其排序,然后使用
groupby
,也可以使用
collections.OrderedDict
(如果顺序重要)或
collections.defaultdict
在O(N)时间内进行排序:

更新:

我发现您只希望返回那些我们没有用于分组的密钥,因此您需要执行以下操作:

>>> group_keys = {'a'}
>>> {k:[{k:d[k] for k in d.viewkeys() - group_keys} for d in g]
                                   for k, g in groupby(items, itemgetter(*group_keys))}
{1: [{'c': 8, 'b': 9},
     {'c': 4, 'b': 5}],
 2: [{'c': 1, 'b': 3},
     {'c': 9, 'b': 7}],
 3: [{'c': 2, 'b': 8}]}

注意:此代码假定数据已排序。如果不是,我们必须手动排序

from itertools import groupby
print {key:list(grp) for key, grp in groupby(items, key=lambda x:x["a"])}
输出

{1: [{'a': 1, 'b': 9, 'c': 8}, {'a': 1, 'b': 5, 'c': 4}],
 2: [{'a': 2, 'b': 3, 'c': 1}, {'a': 2, 'b': 7, 'c': 9}],
 3: [{'a': 3, 'b': 8, 'c': 2}]}
{1: [{'c': 8, 'b': 9}, {'c': 4, 'b': 5}],
 2: [{'c': 1, 'b': 3}, {'c': 9, 'b': 7}],
 3: [{'c': 2, 'b': 8}]}
要以您要求的相同格式获得结果

from itertools import groupby
from operator import itemgetter
a_getter, getter, keys = itemgetter("a"), itemgetter("b", "c"), ("b", "c")

def recon_dicts(items):
    return dict(zip(keys, getter(items)))

{key: map(recon_dicts, grp) for key, grp in groupby(items, key=a_getter)}
输出

{1: [{'a': 1, 'b': 9, 'c': 8}, {'a': 1, 'b': 5, 'c': 4}],
 2: [{'a': 2, 'b': 3, 'c': 1}, {'a': 2, 'b': 7, 'c': 9}],
 3: [{'a': 3, 'b': 8, 'c': 2}]}
{1: [{'c': 8, 'b': 9}, {'c': 4, 'b': 5}],
 2: [{'c': 1, 'b': 3}, {'c': 9, 'b': 7}],
 3: [{'c': 2, 'b': 8}]}
如果数据尚未排序,可以使用中的
defaultdict
方法,也可以使用
sorted
函数根据
a
进行排序,如下所示

{key: map(recon_dicts, grp)
   for key, grp in groupby(sorted(items, key=a_getter), key=a_getter)}
参考文献:

  • ,


  • 请尽量不要结束这个问题。这里有一些很好的答案,但在相关问题中没有涉及。实际上,Martijn在另一个答案中建议的方法是核心思想。我们的答案建立在同一个想法上:)