I'm trying to convert some data in a list to a dictionary. However, I want this dictionary to have multiple keys with multiple values, for example:
The list:
titles = [ "title1", "title2" ]
ids = [ 1, 2 ]
The dictionary:
dictionary = { "title" : "title1", "title2", "id" : 1, 2 }
Sort of like a JSON idea...
There are actually quite a few entries in the lists, so I can't do them each manually. I could use a loop, I suppose?
You probably want a defaultdict:
>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> d['title'].append('title1')
>>> d['title'].append('title2')
>>> print d
defaultdict(<type 'list'>, {'title': ['title1', 'title2']})
In your case, however, you can simply do:
dictionary = {'title':titles, 'id':ids}
You can link items together using tuples also if you'd prefer (using parentheses). This way you can access multiple items with one key. I don't quite know if this is what you're looking for, but I hope it helps.
dictionary = { "title" : ("title1", "title2"), "id" : (1, 2) }
#dictionary[title][0] returns "title1"
#dictionary[title][1] returns "title2"
More info on tuples:
http://docs.python.org/release/1.5.1p1/tut/tuples.html
you can also try this:
>>> titles = ["t1","t2"]
>>> ids = [1,2]
>>> dct = {"titles": titles, "ids":ids}
>>> dct
{'titles': ['t1', 't2'], 'ids': [1, 2]}
Another solution is using dict setdefault function
>>> d = {}
>>> d.setdefault('title', []).append('title1')
>>> d.setdefault('title', []).append('title2')
>>> d
{'title': ['title1', 'title2']}
Related
I'm not sure if this is even possible but it's worth a shot asking.
I want to be able to access the value from indexing one of the values.
The first thing that came to mind was this but of course, it didn't work.
dict = {['name1', 'name2'] : 'value1'}
print(dict.get('name1))
You can use a tuple (as it's immutable) as a dict key if you need to access it by a pair (or more) of strings (or other immutable values):
>>> d = {}
>>> d[("foo", "bar")] = 6
>>> d[("foo", "baz")] = 8
>>> d
{('foo', 'bar'): 6, ('foo', 'baz'): 8}
>>> d[("foo", "baz")]
8
>>>
This isn't "a key having multiple names", though, it's just a key that happens to be built of multiple strings.
Edit
As discussed in the comments, the end goal is to have multiple keys for each (static) value. That can be succinctly accomplished with an inverted dict first, which is then "flipped" using dict.fromkeys():
def foobar():
pass
def spameggs():
pass
func_to_names = {
foobar: ("foo", "bar", "fb", "foobar"),
spameggs: ("spam", "eggs", "se", "breakfast"),
}
name_to_func = {}
for func, names in func_to_names.items():
name_to_func.update(dict.fromkeys(names, func))
If we tried it you way using:
# Creating a dictionary
myDict = {[1, 2]: 'Names'}
print(myDict)
We get an output of:
TypeError: unhashable type: 'list'
To get around this, we can use this method:
# Creating an empty dictionary
myDict = {}
# Adding list as value
myDict["key1"] = [1, 2]
myDict["key2"] = ["Jim", "Jeff", "Jack"]
print(myDict)
I get a list here:
my_list=["Alex:1990:London",
"Tony:1993:NYC",
"Kate:2001:Beijing",
"Tony:2001:LA",
"Alex:1978:Shanghai"]
How can I get the target dictionary my_target_dict from my_list in the easiest way?
my_target_dict={
"Alex":["Alex:1990:London", "Alex:1978:Shanghai"],
"Tony":["Tony:1993:NYC", "Tony:2001:LA"],
"Kate":["Kate:2001:Beijing"]
}
Use a defaultdict:
>>> from collections import defaultdict
>>> my_list=["Alex:1990:London", "Tony:1993:NYC", "Kate:2001:Beijing", "Tony:2001:LA", "Alex:1978:Shanghai"]
>>> d = defaultdict(list)
>>> for item in my_list:
... name, *_ = item.partition(":")
... d[name].append(item)
...
>>> d
defaultdict(<class 'list'>, {'Alex': ['Alex:1990:London', 'Alex:1978:Shanghai'], 'Tony': ['Tony:1993:NYC', 'Tony:2001:LA'], 'Kate': ['Kate:2001:Beijing']})
>>> d["Alex"]
['Alex:1990:London', 'Alex:1978:Shanghai']
You can use this comprehension to clean the list wrapped single items:
>>> {k:v if len(v) > 1 else v[0] for k,v in d.items()}
{'Alex': ['Alex:1990:London', 'Alex:1978:Shanghai'], 'Tony': ['Tony:1993:NYC', 'Tony:2001:LA'], 'Kate': 'Kate:2001:Beijing'}
In case you intend to work strictly with lists and dictionaries alone, try this:
my_target_dict=dict()
for value in my_list:
key=value.split(':')[0]
if key in my_target_dict:
my_target_dict[key].append(value)
else:
my_target_dict[key]=[value]
print(my_target_dict)
This is my solution for you:
my_list=["Alex:1990:London", "Tony:1993:NYC", "Kate:2001:Beijing", "Tony:2001:LA", "Alex:1978:Shanghai"]
dict = {}
for idx, content in enumerate(my_list):
name = content[:(content.index(':'))]
if name not in dict:
dict[name] = []
dict[name].append(my_list[idx])
First if you don't know about enumerate, it count your index and
take the content in each element of list.
Second, take name of there people by basic python of string. I use name = content[:(content.index(':'))] in order to take string from start to the first symbol ":".
Third, check if the key of dict exist or not. Otherwise, it will delete all your element in list of that key.
Last but not least, append the element you want into your key dict.
Your finally result:
{'Alex': ['Alex:1990:London', 'Alex:1978:Shanghai'], 'Tony': ['Tony:1993:NYC', 'Tony:2001:LA'], 'Kate': ['Kate:2001:Beijing']}
If you are a beginner (as I see) and don't want to use Python's collections module and do the implementation from scratch (it's imp to understand the concept of background work which collection does).
Once you are familiar with this, you can go with collections module and that is beautiful as it has many classes like defaultdict, OrderedDict etc. which can boost the speed of your work.
Here is what I have tried (do not forget to read the commented lines).
I have written a function named get_my_target_dict() which takes my_list and returns my_target_dict. And this is the modular implemenation (that you should prefer).
re is a module to work with regular expressions. Here it is used to match "Alex: 1990 : London" (i.e. spaces around :) kind of strings if any (by mistake).
import re
def get_my_target_dict(my_list):
my_target_dict = {} # dictionary
for string in my_list:
# "Alex:1990:London" => ["Alex", "1990", "London"]
# "Alex : 1990: London" => ["Alex", "1990", "London"]
items = re.split(r"\s*:\s*", string) # `\s*` is to match spaces around `:`
print(items)
# Alex, Tony etc.
key = items[0]
if key in my_target_dict:
my_target_dict[key].append(string)
else:
my_target_dict[key] = [string]
return my_target_dict
if __name__ == "__main__":
my_list=["Alex:1990:London",
"Tony:1993:NYC",
"Kate:2001:Beijing",
"Tony:2001:LA",
"Alex:1978:Shanghai"]
# Call get_my_target_dict(), pass my_list & get my_target_dict
my_target_dict = get_my_target_dict(my_list)
print(my_target_dict)
# {'Alex': ['Alex:1990:London', 'Alex:1978:Shanghai'], 'Tony': ['Tony:1993:NYC', 'Tony:2001:LA'], 'Kate': ['Kate:2001:Beijing']}
# Pretty printing dictionary
import json
print(json.dumps(my_target_dict, indent=4))
# {
# "Alex": [
# "Alex:1990:London",
# "Alex:1978:Shanghai"
# ],
# "Tony": [
# "Tony:1993:NYC",
# "Tony:2001:LA"
# ],
# "Kate": [
# "Kate:2001:Beijing"
# ]
# }
I have dictionary with three-level nesting, eg:
d = {
'sp1':{
'a1':{'c1':2,'c2':3},
'a2':{'c3':1,'c4':4}
},
'sp2':{
'a1':{'c1':3,'c2':3},
'a2':{'c3':2,'c4':0}
}
}
All 2nd-level dictionaries contain the same elements, so I want to change it to
d2 = {'a1':{'c1':{'sp1':2,'sp2':3}, 'c2':{'sp1':3,'sp2':3}}}
i.e. essentially switch nesting order. But when I write code like
d2 = {}
d2['a1']['c1']['sp1'] = 2
It just throws KeyError with whatever values happens to be 'a1'. How do I perform such operation?
If you are doing it manually like the snippet you tried, this is how you should be doing it:
>>> d = {
... 'sp1':{
... 'a1':{'c1':2,'c2':3},
... 'a2':{'c3':1,'c4':4}
... },
... 'sp2':{
... 'a1':{'c1':3,'c2':3},
... 'a2':{'c3':2,'c4':0}
... }
... }
>>>
>>> e = {}
>>> e['a1'] = {}
>>> e['a1']['c1'] = {}
>>> e['a1']['c1']['sp1'] = d['sp1']['a1']['c1']
>>> e['a1']['c2'] = {}
>>> e['a1']['c2']['sp1'] = d['sp1']['a1']['c2']
>>> e['a2'] = {}
>>> e['a2']['c1'] = {}
>>> e['a2']['c2'] = {}
>>> e['a1']['c1']['sp2'] = d['sp2']['a1']['c1']
>>> e['a1']['c2']['sp2'] = d['sp2']['a1']['c2']
>>> e
{'a1': {'c2': {'sp1': 3, 'sp2': 3}, 'c1': {'sp1': 2, 'sp2': 3}}}
>>>
But it is unclear as to why you are doing it. As OmnipotentEntity suggested in the comments, may be you need to use a different data structure to store the data.
To do this, you can use defaultdict, which allows you to define a default initialization action on a dict.
In your case, you want a reverse-order recursive defaultdict, with a classmethod
reverse_recursive_make() which unrolls and reverses the key order:
when passed in a key-value pair or None, returns a (toplevel) dict
when passed in a dict, recurses into each of the {k:v} pairs
I'm not going to write the code for that because what you want can be much more easily achieved with SQL, like I commented.
FOOTNOTE: your version with lambdas (comment below) is perfect.
(If you insist on using dicts, and not some other data structure)
something like this should work
d_final = {}
for k in d.keys():
d2 = d[k]
for k2 in d2.keys():
d3 = d2[k2]
for k3 in d3.keys():
d4 = d_final.get(k2,{})
d4[k] = d3[k3]
d_final[k2] = d4
I may have my indexing off a little, but that should be about right.
I'm working on an assignment. Is there anyway a dictionary can have duplicate keys and hold the same or different values. Here is an example of what i'm trying to do:
dict = {
'Key1' : 'Helo', 'World'
'Key1' : 'Helo'
'Key1' : 'Helo', 'World'
}
I tried doing this but when I associate any value to key1, it gets added to the same key1.
Is this possible with a dictionary? If not what other data structure I can use to implement this process?
Use dictionaries of lists to hold multiple values.
One way to have multiple values to a key is to use a dictionary of lists.
x = { 'Key1' : ['Hello', 'World'],
'Key2' : ['Howdy', 'Neighbor'],
'Key3' : ['Hey', 'Dude']
}
To get the list you want (or make a new one), I recommend using setdefault.
my_list = x.setdefault(key, [])
Example:
>>> x = {}
>>> x['abc'] = [1,2,3,4]
>>> x
{'abc': [1, 2, 3, 4]}
>>> x.setdefault('xyz', [])
[]
>>> x.setdefault('abc', [])
[1, 2, 3, 4]
>>> x
{'xyz': [], 'abc': [1, 2, 3, 4]}
Using defaultdict for the same functionality
To make this even easier, the collections module has a defaultdict object that simplifies this. Just pass it a constructor/factory.
from collections import defaultdict
x = defaultdict(list)
x['key1'].append(12)
x['key1'].append(13)
You can also use dictionaries of dictionaries or even dictionaries of sets.
>>> from collections import defaultdict
>>> dd = defaultdict(dict)
>>> dd
defaultdict(<type 'dict'>, {})
>>> dd['x']['a'] = 23
>>> dd
defaultdict(<type 'dict'>, {'x': {'a': 23}})
>>> dd['x']['b'] = 46
>>> dd['y']['a'] = 12
>>> dd
defaultdict(<type 'dict'>, {'y': {'a': 12}, 'x': {'a': 23, 'b': 46}})
I think you want collections.defaultdict:
from collections import defaultdict
d = defaultdict(list)
list_of_values = [['Hello', 'World'], 'Hello', ['Hello', 'World']]
for v in list_of_values:
d['Key1'].append(v)
print d
This will deal with duplicate keys, and instead of overwriting the key, it will append something to that list of values.
Keys are unique to the data. Consider using some other value for a key or consider using a different data structure to hold this data.
for example:
don't use a persons address as a unique key because several people might live there.
a person's social security number or a drivers license is a much better unique id of a person.
you can create your own id to force it to be unique.
I have a dict structured as below:
{ 'records':[['15','2013-04-02','Mexico','blah','bleh',1,2],['25','2013-04-02','Italy','meh','heh',3,4]], 'attributes':['id','date','location','descr1','descr2','total1','total2'] }
It was created from json using json.load.
How can I iterate through the records key as to make ['records'][0] a key in a new dict and the remainder of each list in ['records'] be the value for that key.
Something like this is what I am thinking, may not even be possible, I am new to Python:
{ '15':['2013-04-02','Mexico','blah','bleh',1,2], '25':['2013-04-02','Italy','meh','heh',3,4] }
Could someone point me in the right direction to going about iterating through the original dict to create the new one?
If d is your dictionary:
In [5]: {rec[0]:rec[1:] for rec in d['records']}
Out[5]:
{'15': ['2013-04-02', 'Mexico', 'blah', 'bleh', 1, 2],
'25': ['2013-04-02', 'Italy', 'meh', 'heh', 3, 4]}
rec_lsts = orgi_dict['records']
new_dict = {}
for l_list in rec_lsts:
new_dict[l_lst[0]] = l_lst[1:]
d = { 'records':[['15','2013-04-02','Mexico','blah','bleh',1,2], ['25','2013-04-02','Italy','meh','heh',3,4]], 'attributes':['id','date','location','descr1','descr2','total1','total2']}
new_d = {}
for a in d['records']:
new_d[a[0]] = a[1:]
print new_d