I have a question about a dictionary I want to make. My goal is to have multiple keys to a single value, like below:
dictionary = {('a', 'b'): 1, ('c', 'd'): 2}
assert dictionary['a'] == 1
assert dictionary['b'] == 1
Any ideas?
I have a question about a dictionary I want to make. My goal is to have multiple keys to a single value, like below:
dictionary = {('a', 'b'): 1, ('c', 'd'): 2}
assert dictionary['a'] == 1
assert dictionary['b'] == 1
Any ideas?
I guess you mean this:
class Value:
def __init__(self, v=None):
self.v = v
v1 = Value(1)
v2 = Value(2)
d = {'a': v1, 'b': v1, 'c': v2, 'd': v2}
d['a'].v += 1
d['b'].v == 2 # True
d['a']
and d['b']
to point to the same value that "updates" as it changes, make the value refer to a mutable object (user-defined class like above, or a dict
, list
, set
).d['a']
, d['b']
changes at same time because they both point to same object.If you're going to be adding to this dictionary frequently you'd want to take a class based approach, something similar to @Latty's answer in this SO question 2d-dictionary-with-many-keys-that-will-return-the-same-value.
However, if you have a static dictionary, and you need only access values by multiple keys then you could just go the very simple route of using two dictionaries. One to store the alias key association and one to store your actual data:
alias = {
'a': 'id1',
'b': 'id1',
'c': 'id2',
'd': 'id2'
}
dictionary = {
'id1': 1,
'id2': 2
}
dictionary[alias['a']]
If you need to add to the dictionary you could write a function like this for using both dictionaries:
def add(key, id, value=None)
if id in dictionary:
if key in alias:
# Do nothing
pass
else:
alias[key] = id
else:
dictionary[id] = value
alias[key] = id
add('e', 'id2')
add('f', 'id3', 3)
While this works, I think ultimately if you want to do something like this writing your own data structure is probably the way to go, though it could use a similar structure.
Your example creates multiple key: value pairs if using fromkeys
. If you don't want this, you can use one key and create an alias for the key. For example if you are using a register map, your key can be the register address and the alias can be register name. That way you can perform read/write operations on the correct register.
>>> mydict = {}
>>> mydict[(1,2)] = [30, 20]
>>> alias1 = (1,2)
>>> print mydict[alias1]
[30, 20]
>>> mydict[(1,3)] = [30, 30]
>>> print mydict
{(1, 2): [30, 20], (1, 3): [30, 30]}
>>> alias1 in mydict
True
It is simple. The first thing that you have to understand the design of the Python interpreter. It doesn't allocate memory for all the variables basically if any two or more variable has the same value it just map to that value.
let's go to the code example,
In [6]: a = 10
In [7]: id(a)
Out[7]: 10914656
In [8]: b = 10
In [9]: id(b)
Out[9]: 10914656
In [10]: c = 11
In [11]: id(c)
Out[11]: 10914688
In [12]: d = 21
In [13]: id(d)
Out[13]: 10915008
In [14]: e = 11
In [15]: id(e)
Out[15]: 10914688
In [16]: e = 21
In [17]: id(e)
Out[17]: 10915008
In [18]: e is d
Out[18]: True
In [19]: e = 30
In [20]: id(e)
Out[20]: 10915296
From the above output, variables a and b shares the same memory, c and d has different memory when I create a new variable e and store a value (11) which is already present in the variable c so it mapped to that memory location and doesn't create a new memory when I change the value present in the variable e to 21 which is already present in the variable d so now variables d and e share the same memory location. At last, I change the value in the variable e to 30 which is not stored in any other variable so it creates a new memory for e.
so any variable which is having same value shares the memory.
Not for list and dictionary objects
let's come to your question.
when multiple keys have same value then all shares same memory so the thing that you expect is already there in python.
you can simply use it like this
In [49]: dictionary = {
...: 'k1':1,
...: 'k2':1,
...: 'k3':2,
...: 'k4':2}
...:
...:
In [50]: id(dictionary['k1'])
Out[50]: 10914368
In [51]: id(dictionary['k2'])
Out[51]: 10914368
In [52]: id(dictionary['k3'])
Out[52]: 10914400
In [53]: id(dictionary['k4'])
Out[53]: 10914400
From the above output, the key k1 and k2 mapped to the same address which means value one stored only once in the memory which is multiple key single value dictionary this is the thing you want. :P
HAVING MULTIPLE KEYS
#!/usr/bin/env python3
def get_keys(s):
# Lower the user's entry to easily manipulate data
s = s.lower()
# Create a list to simulate multiple keys
numbers = ['uno', 'one', 'um', 'eins', 'ein']
# Lambda for input validation
validator = lambda key: key if key in numbers else 'no-key-found' # return me x if x is found in the list numbers, contratiwise return me 'no-key-found'
dic = {
validator(s):'1',
'no-key-found':'Key does not exist'
}
return dic[validator(s)]
print(get_keys(input('Type in word: ')))
HAVING DYNAMIC KEYS
#!/usr/bin/env python3
import sys
def week_days():
# Assets
number_day = ['1', '2', '3', '4', '5', '6', '7']
# Introduction
print('Welcome to the Week Day Finder')
# User input
day = input('Please, enter the day you want to check: ').lower()
WEEK_COLOR = {'RED': '\u001b[31m', 'GREEN': '\u001b[32m'}
# Day validator
days = {
'1' if day in number_day else 'sunday': 'Weekend Day',
'2' if day in number_day else 'monday': 'Week Day',
'3' if day in number_day else 'tuesday': 'Week Day',
'4' if day in number_day else 'wednesday': 'Week Day',
'5' if day in number_day else 'thursday': 'Week Day',
'6' if day in number_day else 'friday': 'Week Day',
'7' if day in number_day else 'saturday': 'Weekend Day'
}
# Logical trial
try:
if days[day] == 'Week Day':
print(WEEK_COLOR['GREEN'], days[day])
else:
print(WEEK_COLOR['RED'], days[day])
except KeyError:
print('** Invalid Day **', file=sys.stderr)
def main():
week_days()
if __name__ == '__main__':
main()
Having fun for using the destructuring assignment:
dictionary = {
**dict.fromkeys(['a', 'b'], 1),
**dict.fromkeys(['c', 'd'], 2),
}
assert dictionary['a'] == 1
assert dictionary['b'] == 1
# Elegant!!