What you are trying to do is not possible with dictionaries. In fact, it is contrary to the whole idea behind dictionaries.
Also, your Sets class won't help you, as it effectively gives each name a new (sort of random) hash code, making it difficult to retrieve items from the dictionary, other than checking all the items, which defeats the purpose of the dict. You can not do dict.get(Sets(some_name)), as this will create a new Sets object, having a different hash code than the one already in the dictionary!
What you can do instead is:
Just create a list of
(name, value)pairs, orpairs = zip(names, values) # or list(zip(...)) in Python 3create a dictionary mapping names to lists of values.
dictionary = {} for n, v in zip(names, values): dictionary.setdefault(n, []).append(v)
The first approach, using lists of tuples, will have linear lookup time (you basically have to check all the entries), but the second one, a dict mapping to lists, is as close as you can get to "multi-key-dicts" and should serve your purposes well. To access the values per key, do this:
for key, values in dictionary.iteritems():
for value in values:
print key, value
Answer from tobias_k on Stack OverflowWhat you are trying to do is not possible with dictionaries. In fact, it is contrary to the whole idea behind dictionaries.
Also, your Sets class won't help you, as it effectively gives each name a new (sort of random) hash code, making it difficult to retrieve items from the dictionary, other than checking all the items, which defeats the purpose of the dict. You can not do dict.get(Sets(some_name)), as this will create a new Sets object, having a different hash code than the one already in the dictionary!
What you can do instead is:
Just create a list of
(name, value)pairs, orpairs = zip(names, values) # or list(zip(...)) in Python 3create a dictionary mapping names to lists of values.
dictionary = {} for n, v in zip(names, values): dictionary.setdefault(n, []).append(v)
The first approach, using lists of tuples, will have linear lookup time (you basically have to check all the entries), but the second one, a dict mapping to lists, is as close as you can get to "multi-key-dicts" and should serve your purposes well. To access the values per key, do this:
for key, values in dictionary.iteritems():
for value in values:
print key, value
Instead of wanting multiple keys with the same name, could you getting away of having multiple values per each key?
names = [1]
values = [[1, 2, 3], [4, 5, 6]]
dict = {}
for i in names:
dict[i] = values
for k,v in dict.items():
for v in dict[k]:
print("key: {} :: v: {}".format(k, v))
Output:
key: 1 :: v: [1, 2, 3]
key: 1 :: v: [4, 5, 6]
Then you would access each value like this (or in a loop):
print("Key 1 value 1: {}".format(dict[1][0]))
print("Key 1 value 2: {}".format(dict[1][1]))
ie
dict = { a : 10 , a : [30,10]}
dictionary - Keys with same name with multiple Values in python - Stack Overflow
list - Python Dictionary with multiple keys with same name problem - Stack Overflow
in python, can there be multiple keys of the same name within one dictionary? if so, how would you delete a specific one? - Stack Overflow
python - A dictionary that allows multiple keys for one value - Code Review Stack Exchange
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
- Python's strings and numbers are immutable objects,
- So, if you want
d['a']andd['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 adict,list,set). - Then, when you modify the object at
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.
One way is to put the value in the list for "Randy", as in dictionary we can't have multiple keys of same name. Here is the solution for the same,
class FileOwners:
@staticmethod
def group_by_owners(files):
d={}
for i in files:
if files[i] in d:
d[files[i]].append(i)
else:
d[files[i]]=[i]
return d
files = {
'Input.txt': 'Randy',
'Code.py': 'Stan',
'Output.txt': 'Randy'
}
print(FileOwners.group_by_owners(files))
You can't have the same key in a dict. For your example, use owner as key and the value will be a list of files.
Something like this:
class FileOwners:
@staticmethod
def group_by_owners(files):
result = {}
for _f in list(files.keys()):
if not files[_f] in result.keys():
result[files[_f]] = []
result[files[_f]].append(_f)
return result
files = {
'Input.txt': 'Randy',
'Code.py': 'Stan',
'Output.txt': 'Randy'
}
print(FileOwners.group_by_owners(files))
No, Dictionary must have unique key since it uses hashing algorithm
If you think you need this your best move is probably to put a list into a dictionary. It's quite a bit more code to handle but it gets the job done.
On the other hand, needing to ask this question is usually, but not always, a sign you're doing something wrong.
For consistency, you should have the dictionary map keys to lists (or sets) of values, of which some can be empty. There is a nice idiom for this:
from collections import defaultdict
d = defaultdict(set)
d["key"].add(...)
(A defaultdict is like a normal dictionary, but if a key is missing it will call the argument you passed in when you instantiated it and use the result as the default value. So this will automatically create an empty set of values if you ask for a key which isn't already present.)
If you need the object to look more like a dictionary (i.e. to set a value by d["key"] = ...) you can do the following. But this is probably a bad idea, because it goes against the normal Python syntax, and is likely to come back and bite you later. Especially if someone else has to maintain your code.
class Multidict(defaultdict):
def __init__(self):
super(Multidict, self).__init__(set)
def __setitem__(self, key, value):
if isinstance(value, (self.default_factory)): # self.default_factory is `set`
super().__setitem__(key, value)
else:
self[key].append(value)
I haven't tested this.
You can also try paste.util.multidict.MultiDict
$ easy_install Paste
Then:
from paste.util.multidict import MultiDict
d = MultiDict()
d.add('a', 1)
d.add('a', 2)
d.add('b', 3)
d.mixed()
>>> {'a': [1, 2], 'b': 3}
d.getall('a')
>>> [1, 2]
d.getall('b')
>>> [3]
Web frameworks like Pylons are using this library to handle HTTP query string/post data, which can have same-name keys.
You could do something like:
import itertools as it
unique_dict = {}
value_key=lambda x: x[1]
sorted_items = sorted(your_current_dict.items(), key=value_key)
for value, group in it.groupby(sorted_items, key=value_key):
for key in group:
unique_dict[key] = value
This transforms your dictionary into a dictionary where equal values of any kind(but comparable) are unique. If your values are not comparable(but are hashable) you could use a temporary dict:
from collections import defaultdict
unique_dict = {}
tmp_dict = defaultdict(list)
for key, value in your_current_dict.items():
tmp_dict[value].append(key)
for value, keys in tmp_dict.items():
unique_dict.update(zip(keys, [value] * len(keys)))
If you happen to be using python 3, sys.intern offers a very elegant solution:
for k in persons:
persons[k] = sys.intern(persons[k])
In Python 2.7, you can do roughly the same thing with one extra step:
interned = { v:v for v in set(persons.itervalues()) }
for k in persons:
persons[k] = interned[persons[k]]
In 2.x (< 2.7), you can write interned = dict( (v, v) for … ) instead.