как группировать словари с помощью itemgetter - PullRequest
1 голос
/ 16 июня 2020

У меня есть такой список словарей:

students = [
    {'name': 'alex','class': 'A'},
    {'name': 'richard','class': 'A'},
    {'name': 'john','class': 'C'},
    {'name': 'harry','class': 'B'},
    {'name': 'rudolf','class': 'B'},
    {'name': 'charlie','class': 'E'},
    {'name': 'budi','class': 'C'},
    {'name': 'gabriel','class': 'B'},
    {'name': 'dessy', 'class': 'B'}
]

Я хотел бы сгруппировать эти словари по классам, добавить их в список и добавить каждый список в список:

[[{'name': 'alex', 'class': 'A'},
 {'name': 'richard', 'class': 'A'}],
 [{'name': 'harry', 'class': 'B'},
 {'name': 'rudolf', 'class': 'B'},
 {'name': 'gabriel', 'class': 'B'},
 {'name': 'dessy', 'class': 'B'}],
 [{'name': 'john', 'class': 'C'},
 {'name': 'budi', 'class': 'C'}],
 [{'name': 'charlie', 'class': 'E'}]]

Я знаю, как отсортировать предыдущий список с помощью itemgetter:

import itertools
from operator import itemgetter
students = sorted(students, key=itemgetter('class'))

Как я могу сгруппировать их в список и создать список списков? Кроме того, в этом случае было бы лучше использовать наборы (порядок не имеет значения, если словари сгруппированы по классам).

Ответы [ 3 ]

3 голосов
/ 16 июня 2020

Вы можете сделать это с помощью defaultdict

from collections import defaultdict

res = defaultdict(list)
for i in students:
    res[i['class']].append(i)
print(list(res.values()))

Output

[[{'name': 'alex', 'class': 'A'}, {'name': 'richard', 'class': 'A'}],
 [{'name': 'john', 'class': 'C'}, {'name': 'budi', 'class': 'C'}],
 [{'name': 'harry', 'class': 'B'},
  {'name': 'rudolf', 'class': 'B'},
  {'name': 'gabriel', 'class': 'B'},
  {'name': 'dessy', 'class': 'B'}],
 [{'name': 'charlie', 'class': 'E'}]]
2 голосов
/ 16 июня 2020

groupby на помощь:

In [37]: from itertools import groupby

In [38]: from operator import itemgetter

In [39]: students.sort(key=itemgetter('class'))

In [40]: [list(v) for _, v in groupby(students, itemgetter('class'))]
Out[40]:
[[{'name': 'alex', 'class': 'A'}, {'name': 'richard', 'class': 'A'}],
 [{'name': 'harry', 'class': 'B'},
  {'name': 'rudolf', 'class': 'B'},
  {'name': 'gabriel', 'class': 'B'},
  {'name': 'dessy', 'class': 'B'}],
 [{'name': 'john', 'class': 'C'}, {'name': 'budi', 'class': 'C'}],
 [{'name': 'charlie', 'class': 'E'}]]

вы также можете, если хотите, выключить класс в dict:

In [41]: {k: list(v) for k, v in groupby(students, itemgetter('class'))}
Out[41]:
{'A': [{'name': 'alex', 'class': 'A'}, {'name': 'richard', 'class': 'A'}],
 'B': [{'name': 'harry', 'class': 'B'},
  {'name': 'rudolf', 'class': 'B'},
  {'name': 'gabriel', 'class': 'B'},
  {'name': 'dessy', 'class': 'B'}],
 'C': [{'name': 'john', 'class': 'C'}, {'name': 'budi', 'class': 'C'}],
 'E': [{'name': 'charlie', 'class': 'E'}]}
0 голосов
/ 16 июня 2020

Если вы хотите сделать это «вручную»:

students = [
    {'name': 'alex','class': 'A'},
    {'name': 'richard','class': 'A'},
    {'name': 'john','class': 'C'},
    {'name': 'harry','class': 'B'},
    {'name': 'rudolf','class': 'B'},
    {'name': 'charlie','class': 'E'},
    {'name': 'budi','class': 'C'},
    {'name': 'gabriel','class': 'B'},
    {'name': 'dessy', 'class': 'B'}
]

classes = dict()

for student in students:
    if student['class'] not in classes:
        classes[student['class']] = []
    classes[student['class']].append(student['name'])
    
all = []
for classroom in sorted(classes.keys()):
    all.append([])
    
    for student in classes[classroom]:
        all[-1].append({'name':student,'class':classroom})
    
print (all)
...