Группируйте пары ключ / значение в словаре Python по значению, сохраняя исходные ассоциации ключей - PullRequest
0 голосов
/ 24 сентября 2018

В поисках эффективного подхода к группированию значений из словаря по их подобию, в результате получается перевернутый словарь с исходными ключами, сгруппированными в виде списка.Я могу придумать хитрые способы сделать это, но меня интересуют другие подходы.

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

{'d1': {'goober': True, 'horse': 42},
 'd2': {'goober': True, 'horse': 42},
 'd3': {'goober': False, 'horse': 71}}

И мой нужный словарь может выглядетьнапример:

{'group1': {'dict': {'goober': True, 'horse': 42}, 'keys': ['d1', 'd2']},
 'group2': {'dict': {'goober': False, 'horse': 71}, 'keys': ['d3']}}

Важная деталь заключается в том, что исходные ключи d1 и d2 были сгруппированы под произвольным именем group1, сгруппированы по идентичным словарям из исходного словаря.Поддержание оригинальных ключей - d1 и d2, хранящихся в списке keys - также важно, и с каким словарем они были связаны.d3 один, потому что его словарь уникален.

Моя большая цель - взять словарь словаря, который содержит параметры для других целей, но сгруппировать их там, где параметры идентичны, так что я могу быть болееэффективно и запустить их вместе.

Любые советы или предложения будут оценены!

Ответы [ 3 ]

0 голосов
/ 24 сентября 2018

Вот как бы я это сделал

dicts = {
'd1': {'goober': True, 'horse': 42}, 
'd2': {'goober': True, 'horse': 42},
'd3': {'goober': False, 'horse': 71}
}

desired_dict = {}
group_num = 0

for d in dicts:
    for dd in desired_dict: # check if the dict exists in out desired_dict
        if desired_dict[dd]['dict'] == dicts[d]: # if yes, just update the keys
            desired_dict[dd].get('keys', []).append(d)
            break
    else:
        group_num += 1 # else make a new dictionary group
        group_name = 'group{0}'.format(group_num)
        desired_dict[group_name] = {'dict': dicts[d], 'keys': [d, ]}

print(desired_dict)


Out: {'group1': {'dict': {'goober': True, 'horse': 42}, 'keys': ['d1', 'd2']}, 
      'group2': {'dict': {'goober': False, 'horse': 71}, 'keys': ['d3']}} 
0 голосов
/ 24 сентября 2018

Вы можете использовать itertools.groupby:

d = {'d1': {'goober': True, 'horse': 42},
     'd2': {'goober': True, 'horse': 42},
     'd3': {'goober': False, 'horse': 71}}
from itertools import groupby
from operator import itemgetter
l = [{'dict': k, 'keys': list(map(itemgetter(0), g))} for k, g in groupby(sorted(d.items(), key=lambda t: t[1].items()), itemgetter(1))]

, чтобы l стало:

[{'dict': {'goober': True, 'horse': 42}, 'keys': ['d1', 'd2']}, {'dict': {'goober': False, 'horse': 71}, 'keys': ['d3']}]

0 голосов
/ 24 сентября 2018

Это возможно, но утомительно с обычным Python.Если вы хотите использовать стороннюю библиотеку, вы можете использовать Pandas для выполнения агрегации GroupBy:

import pandas as pd

d = {'d1': {'goober': True, 'horse': 42},
     'd2': {'goober': True, 'horse': 42},
     'd3': {'goober': False, 'horse': 71}}

df = pd.DataFrame(d).T.reset_index().groupby('goober')\
                    .agg(lambda x: set(x)).reset_index()

print(df)

#   goober     index horse
# 0  False      {d3}  {71}
# 1   True  {d1, d2}  {42}

res = [{'dict': {'goober': row.goober, 'horse': next(iter(row.horse))},
        'keys': list(row.index)} for row in df.itertuples(index=False)]

Результат:

[{'dict': {'goober': False, 'horse': 71}, 'keys': ['d3']},
 {'dict': {'goober': True, 'horse': 42}, 'keys': ['d1', 'd2']}]

Примечание. Я не применял никакихлогика для получения 'group1' и 'group2' ключей внешнего словаря.Неясно как они получены.Если они являются произвольными идентификаторами, вы можете использовать enumerate на следующем шаге:

res2 = {f'group{idx}': d for idx, d in enumerate(res, 1)}

Результат:

{'group1': {'dict': {'goober': False, 'horse': 71}, 'keys': ['d3']},
 'group2': {'dict': {'goober': True, 'horse': 42}, 'keys': ['d1', 'd2']}}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...