我有以下 python 字典,其中包含键和值的元组:
{(A, 1): (B, 2),
(C, 3): (D, 4),
(B, 2): (A, 1),
(D, 4): (C, 3),
}
如何在键和值之间获得一组独特的组合?这样的(A,1):(B,2)
出现,不是(B,2):(A,1)
吗?
我有以下 python 字典,其中包含键和值的元组:
{(A, 1): (B, 2),
(C, 3): (D, 4),
(B, 2): (A, 1),
(D, 4): (C, 3),
}
如何在键和值之间获得一组独特的组合?这样的(A,1):(B,2)
出现,不是(B,2):(A,1)
吗?
d = {('A', 1): ('B', 2),
('C', 3): ('D', 4),
('B', 2): ('A', 1),
('D', 4): ('C', 3),
}
>>> dict(set(frozenset(item) for item in d.items()))
{('A', 1): ('B', 2), ('D', 4): ('C', 3)}
这是通过将字典中的每个键/值对转换为一个集合来实现的。这很重要,因为对于任何一对(a, b)
,set([a, b])
等于set([b, a])
。因此,如果我们可以获取所有这些键/值集并将它们添加到一个集合中,这将消除所有重复项,那将是完美的。我们不能对set
类型执行此操作,因为它不可散列,因此我们使用它frozenset
。内置dict()
函数可以接受任何可迭代的键/值对作为参数,因此我们可以传入我们的键/值对集,它会按预期工作。
如果有任何映射到自身,例如,如果你有d[('A', 1)] = ('A', 1)
,解决这个问题,你可以sorted()
按照评论中的建议使用:
d = {('A', 1): ('A', 1),
('C', 3): ('D', 4),
('D', 4): ('C', 3),
}
>>> dict(sorted(item) for item in d.items())
{('A', 1): ('A', 1), ('C', 3): ('D', 4)}
这还有一个好处,即对于任何重复,排序顺序将始终为您提供“较小”的元素作为键和“较大的”作为值。
但是,在 Python 3.x 上,如果您的键和值可能具有不同的类型,则需要注意这一点,因为sorted()
除非迭代中的所有元素都是相同的类型,否则会引发异常:
>>> d = {1: 'A', 'A': 1}
>>> dict(sorted(item) for item in d.items())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
TypeError: unorderable types: int() < str()
这是一种手动方法:
res = {}
seen = set()
for key, val in d.items():
if (val, key) in seen: #no need to check (key, val) since keys are unique
continue
res[key] = val
seen.add((key, val))
使用set
和字典理解:
>>> dic = {('A', 1): ('B', 2), ('C', 3): ('D', 4), ('B', 2): ('A', 1), ('D', 4): ('C', 3)}
>>> seen = set()
>>> { k:v for k,v in dic.items() if (v,k) not in seen and not seen.add((k, v))}
{('A', 1): ('B', 2), ('C', 3): ('D', 4)}
这也适用于自映射键值对:
>>> d = {('A', 1): ('A', 1), ('C', 3): ('D', 4), ('D', 4): ('C', 3)}
>>> seen = set()
>>> { k:v for k,v in d.items() if (v,k) not in seen and not seen.add((k, v))}
{('A', 1): ('A', 1), ('D', 4): ('C', 3)}
上面的代码等价于:
seen = set()
new_dic = {}
for k,v in dic.items():
if v, k not in seen:
new_dic[k] = v
seen.add((k, v))
作为另一种选择:
original_dict = {('A', 1): ('B', 2),
('C', 3): ('D', 4),
('B', 2): ('A', 1),
('D', 4): ('C', 3),
}
new_dict = {}
for a in original_dict.items():
if a[0] > a[1]:
one, two = a[1],a[0]
else:
one,two = a[0],a[1]
new_dict[one] = two