我想按以下字典的值分组:
my_dict = {"Q1": {0: "no", 1: "yes"}, "Q2": {0: "no", 1: "yes"},
"Q3": {1: "animal", 2: "vehicle"}, Q4: {1: "animal", 2: "vehicle"}}
结果应如下所示:
result = {("Q1", "Q2"): {0: "no", 1: "yes"},
("Q3", "Q4"): {1: "animal", 2: "vehicle"}}
我已经尝试过这里列出的解决方案: Grouping Python dictionary keys as a list and create a new dictionary with this list as a value
使用collections.defaultdict无效,因为结果将暗示我用作分组键的字典最终会成为结果字典的键,如下所示:
result = {{0: "no", 1: "yes"}: ["Q1", "Q2"] ,
{1: "animal", 2: "vehicle"}: ["Q3", "Q4"]}
当然这是行不通的,因为字典的键必须是不可变的。因此,我需要像Frozendict这样的东西,而这在python的标准库中是不可用的。
使用itertools.groupby也不起作用,因为它需要对数据进行排序。但是operator.itemgetter不能对字典进行排序。它说:
TypeError: '<' not supported between instances of 'dict' and 'dict'
因此,我想知道一种解决该问题的Python方法!谢谢您的帮助:)
答案 0 :(得分:4)
除了使用frozendict
之外,您还可以使用字典中项目的 frozenset
:
intermediate_dict = defaultdict(list)
for k, v in my_dict.items():
intermediate_dict[frozenset(v.items())].append(k)
result = {tuple(v): dict(k) for k, v in intermediate_dict.items()}
输出:
{('Q1', 'Q2'): {0: 'no', 1: 'yes'}, ('Q3', 'Q4'): {1: 'animal', 2: 'vehicle'}}
以上不假设或要求排序输入,因此在所有情况下都为O(n)
,而排序为O(n log n)
。
答案 1 :(得分:3)
假设按值对字典进行排序,则可以使用itertools.groupby
:
{tuple(g): k for k, g in groupby(my_dict, key=my_dict.get)}
代码:
from itertools import groupby
my_dict = {"Q1": {0: "no", 1: "yes"}, "Q2": {0: "no", 1: "yes"},
"Q3": {1: "animal", 2: "vehicle"}, "Q4": {1: "animal", 2: "vehicle"}}
print({tuple(g): k for k, g in groupby(my_dict, key=my_dict.get)})
# {('Q1', 'Q2'): {0: 'no', 1: 'yes'}, ('Q3', 'Q4'): {1: 'animal', 2: 'vehicle'}}
答案 2 :(得分:0)
因此,我需要像Frozendict这样的东西,这在python的标准库中不可用。
您能详细说明一下吗?尽管frozendict
不在语言标准中,但是您可以安装扩展名:https://pypi.org/project/frozendict/
或者,您可以将字典变成由(key, value)
个项(键排序)组成的元组,以获得不可变,规范且可逆的表示形式,可用作字典键。
(请注意,如果词典中可以包含其他可变值,则可能需要递归执行此操作。)
编辑:如其他答案所指出的,或对项目使用Frozenset()。请注意,这还需要递归确保内部字典的值是不变的。
答案 3 :(得分:0)
这是同时使用frozenset
和groupby
的另一种方式
from operator import itemgetter
from itertools import groupby
first = itemgetter(0)
second = itemgetter(1)
my_hashes = sorted([(k, hash(frozenset(v))) for k, v in my_dict.items()], key=second)
d = dict()
for k, v in groupby(my_hashes, key=second):
items = list(v)
d[tuple(map(first, items))] = my_dict.get(first(first(items)))
print(d)
{('Q3', 'Q4'): {1: 'animal', 2: 'vehicle'}, ('Q1', 'Q2'): {0: 'no', 1: 'yes'}}