Making dictionary from two lists - python

I have two lists
l1 = ['cat','dog']
l2= [1,2]
Now I want to make a dictionary like this:
dict { {'name':cat,'id'=1}{'name':dog,'id'=2}}
I am using zip but that's not fulfilling my requirement.

result = [{'name': name, 'id': id} for (name, id) in zip(l1, l2)]
It doesn't make sense for the container all the individual dicts are in to be a dict as well (unless you want to key it on, say, id).

If you have a lot of keys and you don't want to create dict comprehension and declare what goes where.
l1 = ['cat','dog']
l2= [1,2]
[dict(zip(['name', 'id'], el)) for el in zip(l1,l2)]
Output:
[{'id': 1, 'name': 'cat'}, {'id': 2, 'name': 'dog'}]

Related

Python: Way to build a dictionary with a variable key and append to a list as the value inside a loop

I have a list of dictionaries. I want to loop through this list of dictionary and for each specific name (an attribute inside each dictionary), I want to create a dictionary where the key is the name and the value of this key is a list which dynamically appends to the list in accordance with a specific condition.
For example, I have
d = [{'Name': 'John', 'id': 10},
{'Name': 'Mark', 'id': 21},
{'Name': 'Matthew', 'id': 30},
{'Name': 'Luke', 'id': 11},
{'Name': 'John', 'id': 20}]
I then built a list with only the names using names=[i['Name'] for i in dic1] so I have a list of names. Notice John will appear twice in this list (at the beginning and end). Then, I want to create a for-loop (for name in names), which creates a dictionary 'ID' that for its value is a list which appends this id field as it goes along.
So in the end I'm looking for this ID dictionary to have:
John: [10,20]
Mark: [21]
Matthew: [30]
Luke: [11]
Notice that John has a list length of two because his name appears twice in the list of dictionaries.
But I can't figure out a way to dynamically append these values to a list inside the for-loop. I tried:
ID={[]} #I also tried with just {}
for name in names:
ID[names].append([i['id'] for i in dic1 if i['Name'] == name])
Please let me know how one can accomplish this. Thanks.
Don't loop over the list of names and go searching for every one in the list; that's very inefficient, since you're scanning the whole list all over again for every name. Just loop over the original list once and update the ID dict as you go. Also, if you build the ID dict first, then you can get the list of names from it and avoid another list traversal:
names = ID.keys()
The easiest solution for ID itself is a dictionary with a default value of the empty list; that way ID[name].append will work for names that aren't in the dict yet, instead of blowing up with a KeyError.
from collections import defaultdict
ID = defaultdict(list)
for item in d:
ID[item['Name']].append(item['id'])
You can treat a defaultdict like a normal dict for almost every purpose, but if you need to, you can turn it into a plain dict by calling dict on it:
plain_id = dict(ID)
The Thonnu has a solution using get and list concatenation which works without defaultdict. Here's another take on a no-import solution:
ID = {}
for item in d:
name, number = item['Name'], item['id']
if name in ID:
ID[name].append(number)
else:
ID[name] = [ number ]
Using collections.defaultdict:
from collections import defaultdict
out = defaultdict(list)
for item in dic1:
out[item['Name']].append(item['id'])
print(dict(out))
Or, without any imports:
out = {}
for item in dic1:
out[item['Name']] = out.get(item['Name'], []) + [item['id']]
print(out)
Or, with a list comprehension:
out = {}
[out.update({item['Name']: out.get(item['Name'], []) + [item['id']]}) for item in dic1]
print(out)
Output:
{'John': [10, 20], 'Mark': [21], 'Matthew': [30], 'Luke': [11]}
dic1 = [{'Name': 'John', 'id': 10}, {'Name': 'Mark', 'id': 21}, {'Name': 'Matthew', 'id': 30}, {'Name': 'Luke', 'id': 11}, {'Name': 'John', 'id': 20}]
id_dict = {}
for dic in dic1:
key = dic['Name']
if key in id_dict:
id_dict[key].append(dic['id'])
else:
id_dict[key] = [dic['id']]
print(id_dict) # {'John': [10, 20], 'Mark': [21], 'Matthew': [30], 'Luke': [11]}
You can use defaultdict for this to initiate a dictionary with a default value. In this case the default value will be empty list.
from collections import defaultdict
d=defaultdict(list)
for item in dic1:
d[item['Name']].append(item['id'])
Output
{'John': [10, 20], 'Mark': [21], 'Matthew': [30], 'Luke': [11]} # by converting (not required) into pure dict dict(d)
You can do in a easy version
dic1=[{'Name': 'John', 'id':10}, {'Name': 'Mark', 'id':21},{'Name': 'Matthew', 'id':30}, {'Name': 'Luke', 'id':11}, {'Name': 'John', 'id':20}]
names=[i['Name'] for i in dic1]
ID = {}
for i, name in enumerate(names):
if name in ID:
ID[name].append(dic1[i]['id'])
else:
ID[name] = [dic1[i]['id']]
print(ID)

Python - Return list of dictionaries with unique Key:Value pair

I have a long list of dictionaries that for the most part do not overlap. However, some of the dictionaries have the same 'Name' field and I'd only like unique names in the list of dictionaries. I'd like the first occurrence of the name to be the one that stays and any thereafter be deleted from the list.
I've put a short list below to illustrate the scenario:
myList = [
{'Name':'John', 'Age':'50', 'Height':'70'},
{'Name':'Kathy', 'Age':'43', 'Height':'65'},
{'Name':'John','Age':'46','Height':'68'},
{'Name':'John','Age':'50','Height':'72'}
]
I'd like this list to return the first 'John' and Kathy, but not the second or third Johns and their related information.
An acceptable, but not optimal solution would also be not having dictionaries with the same name next to each other.
You could run over the list and keep a set of unique names. Every time you encounter a new name (i.e., a name that isn't in the set), you add it to the set and the respective dict to the result:
def uniqueNames(dicts):
names = set()
result = []
for d in dicts:
if not d['Name'] in names:
names.add(d['Name'])
result.append(d)
return result
You can easily write a for-loop for this.
def getName(name):
'''Gets first occurence of name in list of dicts.'''
for i in myList:
if i['Name'] == name:
return i
Initial list:
my_list = [
{'Name':'John', 'Age':'50', 'Height':'70'},
{'Name':'Kathy', 'Age':'43', 'Height':'65'},
{'Name':'John','Age':'46','Height':'68'},
{'Name':'John','Age':'50','Height':'72'}
]
The logical (potentially newbie-friendlier) way:
names = set()
new_list = []
for d in my_list:
name = d['Name']
if name not in names:
new_list.append(d)
names.add(d['Name'])
print new_list # [{'Age': '50', 'Name': 'John', 'Height': '70'}, {'Age': '43', 'Name': 'Kathy', 'Height': '65'}]
A one-liner way:
new_list = {d['Name']: d for d in reversed(my_list)}.values()
print new_list # [{'Age': '43', 'Name': 'Kathy', 'Height': '65'}, {'Age': '50', 'Name': 'John', 'Height': '70'}]
Note: The one-liner will contain the first occurrence of each name, but it will return an arbitrarily ordered list.

generate list from values of certain field in list of objects

How would I generate a list of values of a certain field of objects in a list?
Given the list of objects:
[ {name: "Joe", group: 1}, {name: "Kirk", group: 2}, {name: "Bob", group: 1}]
I want to generate list of the name field values:
["Joe", "Kirk", "Bob"]
The built-in filter() function seems to come close, but it will return the entire objects themselves.
I'd like a clean, one line solution such as:
filterLikeFunc(function(obj){return obj.name}, mylist)
Sorry, I know that's c syntax.
Just replace filter built-in function with map built-in function.
And use get function which will not give you key error in the absence of that particular key to get value for name key.
data = [{'name': "Joe", 'group': 1}, {'name': "Kirk", 'group': 2}, {'name': "Bob", 'group': 1}]
print map(lambda x: x.get('name'), data)
In Python 3.x
print(list(map(lambda x: x.get('name'), data)))
Results:
['Joe', 'Kirk', 'Bob']
Using List Comprehension:
print [each.get('name') for each in data]
Using a list comprehension approach you get:
objects = [{'group': 1, 'name': 'Joe'}, {'group': 2, 'name': 'Kirk'}, {'group': 1, 'name': 'Bob'}]
names = [i["name"] for i in objects]
For a good intro to list comprehensions, see https://docs.python.org/2/tutorial/datastructures.html
Just iterate over your list of dicts and pick out the name value and put them in a list.
x = [ {'name': "Joe", 'group': 1}, {'name': "Kirk", 'group': 2}, {'name': "Bob", 'group': 1}]
y = [y['name'] for y in x]
print(y)

how to merge values of python dict in a list of dictionaries

i have a python list of dictionary as shown below:
mylist = [{'id':1,'value':4},{'id':1,'value':6},{'id':2,'value':6},{'id':3,'value':9},{'id':3,'value':56},{'id':3,'value':67},]
i am trying to create a new list of dictionaries like this by doing some operations on the above shown list of dictionaries
newlist = [{'id':1,'value':[4,6]},{'id':2,'value':[6]},{'id':3,'value':[9,56,67]}]
Does anyone know a good way to do this?
If list items are sorted by id, you can use itertools.groupby:
>>> mylist = [{'id':1,'value':4},{'id':1,'value':6},{'id':2,'value':6},{'id':3,'value':9},{'id':3,'value':56},{'id':3,'v alue':67},]
>>> import itertools
>>> [{'id': key, 'value': [x['value'] for x in grp]}
... for key, grp in itertools.groupby(mylist, key=lambda d: d['id'])]
[{'id': 1, 'value': [4, 6]},
{'id': 2, 'value': [6]},
{'id': 3, 'value': [9, 56, 67]}]
You can construct the entire the list of dictionaries as a single dictionary with multiple values, using defaultdict, like this
from collections import defaultdict
d = defaultdict(list)
for item in mylist:
d[item['id']].append(item['value'])
And then using list comprehension, you can reconstruct the required list of dictionaries like this
print[{'id': key, 'value': d[key]} for key in d]
# [{'id':1, 'value':[4, 6]}, {'id':2, 'value':[6]}, {'id':3, 'value':[9,56,67]}]
You could also use dict comprehension:
newlist = {key: [entries[key] for entries in diclist] for key, value in diclist[0].items()}

Adding a key value pair to a list of dicts based on another list Python

Sorry if the title is not clear, but here is what I'm trying to achieve.
I have a list of dicts :
l = [{'name': 'inAnalysis'}, {'name': 'inQuest'}, {'name': 'inDevelopment'}]
And a sort of translation table like this :
tr = {'inAnalysis' : 1, 'inDevelopment' : 2, 'inQuest' : 3}
I want to add the key value to l like this :
l = [{'name': 'inAnalysis', 'order' : 1},
{'name': 'inQuest', 'order' : 3},
{'name': 'inDevelopment', 'order' : 2}]
How can I match the value of l with the key of tr and get its value with the key order and add it to l? Any help would be appreciated. I'm using Python 2.6.
You can use list comprehension to dynamically generate the dictionaries like this
print [{"name":dic["name"], "order":tr[dic["name"]]} for dic in l]
Output
[{'name': 'inAnalysis', 'order': 1},
{'name': 'inQuest', 'order': 3},
{'name': 'inDevelopment', 'order': 2}]
Alternatively, you can use the following
for dic in l: dic["order"] = tr[dic["name"]]
this modifies the dictionaries in-place.
If you want to modify the existing dictionaries in place (note that thefoutheye's solution makes new dictionaries which could concievably be a problem if something else in your code is holding a reference to the dictionaries in the list, rather than the list itself) you can do:
for my_dict in l:
my_dict['order'] = tr[my_dict['name']]

Categories