Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiples-keys dictionary where key order doesn't matter

I am trying to create a dictionary with two strings as a key and I want the keys to be in whatever order.

myDict[('A', 'B')] = 'something'
myDict[('B', 'A')] = 'something else'
print(myDict[('A', 'B')])

I want this piece of code to print 'something else'. Unfortunately, it seems that the ordering matters with tuples. What would be the best data structure to use as the key?

like image 467
lurgan Avatar asked Oct 08 '17 15:10

lurgan


People also ask

Does order of keys matter in dictionary Python?

Changed in Python 3.7 Dictionaries preserve insertion order. Note that updating a key does not affect the order. Keys added after deletion are inserted at the end.

Can a dictionary key have multiple keys?

A dictionary in Python is a mutable, unordered collection of key-value pairs. Creating a dictionary with multiple keys mapped a single value allows a user to modify the value at all keys that share that value at the same time.

Can multiple keys in a dictionary have the same value?

Answer. No, each key in a dictionary should be unique. You can't have two keys with the same value. Attempting to use the same key again will just overwrite the previous value stored.

How do you sort multiple keys in a dictionary Python?

Sort by multiple keys Two dictionaries have the value 'CA' for the key 'State' . If the values are equal, the original order is preserved. You can specify multiple arguments for operator. itemgetter() , and if the values for the first key are equal, they will be compared and sorted by the value of the next key.


1 Answers

Use a frozenset

Instead of a tuple, which is ordered, you can use a frozenset, which is unordered, while still hashable as frozenset is immutable.

myDict = {}
myDict[frozenset(('A', 'B'))] = 'something'
myDict[frozenset(('B', 'A'))] = 'something else'
print(myDict[frozenset(('A', 'B'))])

Which will print:

something else


Unfortunately, this simplicity comes with a disadvantage, since frozenset is basically a “frozen” set. There will be no duplicate values in the frozenset, for example,

frozenset((1, 2)) == frozenset((1,2,2,1,1))

If the trimming down of values doesn’t bother you, feel free to use frozenset

But if you’re 100% sure that you don’t want what was mentioned above to happen, there are however two alternates:


First method is to use a Counter, and make it hashable by using frozenset again: (Note: everything in the tuple must be hashable)

from collections import Counter

myDict = {}
myDict[frozenset(Counter(('A', 'B')).items())] = 'something'
myDict[frozenset(Counter(('B', 'A')).items())] = 'something else'
print(myDict[frozenset(Counter(('A', 'B')).items())])

# something else

Second method is to use the built-in function sorted, and make it hashable by making it a tuple. This will sort the values before being used as a key: (Note: everything in the tuple must be sortable and hashable)

myDict = {}
myDict[tuple(sorted(('A', 'B')))] = 'something'
myDict[tuple(sorted(('B', 'A')))] = 'something else'
print(myDict[tuple(sorted(('A', 'B')))])

# something else

But if the tuple elements are neither all hashable, nor are they all sortable, unfortunately, you might be out of luck and need to create your own dict structure... D:

like image 115
Taku Avatar answered Oct 24 '22 20:10

Taku