Поиск похожих словарей в списке словарей

Нужна помощь с алгоритмом.

Есть есть список из dicts:

[
   { 'id': 1, 'name': 'vasya', 'group_id': 1},
   { 'id': 2, 'name': 'petya', 'group_id': 2},
   { 'id': 3, 'name': 'kolya', 'group_id': 3},
   { 'id': 1, 'name': 'vasya', 'group_id': 4},
   { 'id': 3, 'name': 'kolya', 'group_id': 5}
]

Есть элементы, где повторяются все поля, кроме group_id, мне нужно вытащить все вот такие повторяющиеся элементы, чтобы в итоге преобразовать это к такому виду:

[
   { 'id': 1, 'name': 'vasya', 'group_ids': [1, 4] },
   { 'id': 2, 'name': 'petya', 'group_ids': [2] },
   { 'id': 3, 'name': 'kolya', 'group_ids': [3, 5] },
]

Ответы (3 шт):

Автор решения: MaxU

воспользуйтесь itertools.groupby:

from itertools import groupby

keys = lambda x: (x.get("id"), x.get("name"))

res = [
    dict(
        id=a[0], 
        name=a[1], 
        group_id=[x.get("group_id") for x in b]) 
    for a,b in groupby(sorted(data, key=keys), key=keys)
]

результат:

In [78]: res
Out[78]:
[{'id': 1, 'name': 'vasya', 'group_id': [1, 4]},
 {'id': 2, 'name': 'petya', 'group_id': [2]},
 {'id': 3, 'name': 'kolya', 'group_id': [3, 5]}]
→ Ссылка
Автор решения: strawdog

Вот еще через pandas для разнообразия:

import pandas as pd

lst = [
   { 'id': 1, 'name': 'vasya', 'group_id': 1},
   { 'id': 2, 'name': 'petya', 'group_id': 2},
   { 'id': 3, 'name': 'kolya', 'group_id': 3},
   { 'id': 1, 'name': 'vasya', 'group_id': 4},
   { 'id': 3, 'name': 'kolya', 'group_id': 5}
]

df = pd.DataFrame(lst)
res = df.groupby(["id", "name"]).agg({"id":lambda x:list(x)[0],
                                      "name":lambda x:list(x)[0],
                                      "group_id":list}).to_dict("records")

res:

[{'id': 1, 'name': 'vasya', 'group_id': [1, 4]},
 {'id': 2, 'name': 'petya', 'group_id': [2]},
 {'id': 3, 'name': 'kolya', 'group_id': [3, 5]}]
→ Ссылка
Автор решения: MaxU

Ещё один вариант решения при помощи модуля Pandas:

import pandas as pd

df = pd.DataFrame(data)

res = df.groupby(["id", "name"])["group_id"].apply(list).reset_index().to_dict("records")

результат:

In [126]: res
Out[126]:
[{'id': 1, 'name': 'vasya', 'group_id': [1, 4]},
 {'id': 2, 'name': 'petya', 'group_id': [2]},
 {'id': 3, 'name': 'kolya', 'group_id': [3, 5]}]
→ Ссылка