How to check for redundant combinations in a python dictionary
dictionary, python
Solution
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)}
This works by converting each key/value pair in the dictionary to a set. This is important because for any pair `(a, b)`, `set([a, b])` is equal to `set([b, a])`. So what would be perfect is if we could take all of those key/value sets and add them to a set, which would eliminate all of the duplicates. We can't do this with the `set` type because it isn't hashable, so we use `frozenset` instead. The built-in `dict()` function can accept any iterable of key/value pairs as an argument, so we can pass in our set of key/value pairs and it will work as expected.
A great point was made in comments about this causing an issue if anything maps to itself, for example if you had `d[('A', 1)] = ('A', 1)`, to work around this you can use `sorted()` as suggested in the comment:
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)}
This also has the benefit that for any duplicates the sorted order will consistently give you the "smaller" of the elements as the key and the "larger" as the value.
However on Python 3.x you need to be careful with this if your keys and values may have different types, since `sorted()` will raise an exception unless all of the elements in the iterable are the same type:
>>> 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()
Problem
I have the following python dictionary with tuples for keys and values: ``` {(A, 1): (B, 2), (C, 3): (D, 4), (B, 2): (A, 1), (D, 4): (C, 3), } ``` how do I get a unique set of combinations between keys and values? Such that `(A,1):(B,2)` appears, not `(B,2):(A,1)`?