For example:
persons = [{'id': 1, 'name': 'john'}, {'id': 2, 'name': 'mary'}, {'id': 3, 'name': 'tom'}]
I want to get two lists from it:
ids = [1, 2, 3]
names = ['john', 'mary', 'tom']
What I did:
names = [d['name'] for d in persons]
ids = [d['id'] for d in persons]
Is there a better way to do it?
I'd stick with using list comprehension or use #Woodford technique
ids,name = [dcts['id'] for dcts in persons],[dcts['name'] for dcts in persons]
output
[1, 2, 3]
['john', 'mary', 'tom']
What you did works fine. Another way to handle this (not necessarily better, depending on your needs) is to store your data in a more efficient dictionary and pull the names/ids out of it when you need them:
>>> persons = [{'id': 1, 'name': 'john'}, {'id': 2, 'name': 'mary'}, {'id': 3, 'name': 'tom'}]
>>> p2 = {x['id']: x['name'] for x in persons}
>>> p2
{1: 'john', 2: 'mary', 3: 'tom'}
>>> list(p2.keys())
[1, 2, 3]
>>> list(p2.values())
['john', 'mary', 'tom']
You can do it with pandas in a vectorized fashion:
import pandas as pd
persons = [{'id': 1, 'name': 'john'}, {'id': 2, 'name': 'mary'}, {'id': 3, 'name': 'tom'}]
df = pd.DataFrame(persons)
id_list = df.id.tolist() #[1, 2, 3]
name_list = df.name.tolist() #['john', 'mary', 'tom']
An alternative, inspired by this question, is
ids, names = zip(*map(lambda x: x.values(), persons))
that return tuples. If you need lists
ids, names = map(list, zip(*map(lambda x: x.values(), persons)))
It is a little bit slower on my laptop using python3.9 than the accepted answer but it might be useful.
It sounds like you're trying to iterate through the values of your list while unpacking your dictionaries:
persons = [{'id': 1, 'name': 'john'}, {'id': 2, 'name': 'mary'}, {'id': 3, 'name': 'tom'}]
for x in persons:
id, name = x.values()
ids.append(id)
names.append(name)
Related
I have this
a = [{'name': 'John', 'supporterId': 1}, {'name': 'Paul', 'supporterId': 2}]
b = [{'dependent': 'Erick','supporterId': 2, 'email': 'erick#gmail.com'}, {'dependent': 'Anna', 'supporterId': 2, 'email': 'ana#gmail.com'}, {'dependent': 'George','supporterId': 13}]
and I need to check if the supporterId between a and b are equal and if so put the name_dependent and email inside the corresponding supporterId in a so for example the output to this should be:
c = [{'name': 'John', 'supporterId': 1}, {'name': 'Paul', 'supporterId': 2, 'data': {'dependent': 'Erick','email': 'erick#gmail.com'},
{'dependent': 'Ana','email':'ana#gmail.com'}]
I have tried many for loops inside another but it doesn't seem to work...
I suggest doing it in a couple of steps. First create a way to look up entries in b by supporterId:
>>> b_supporters = {d['supporterId']: d for d in b}
and then use that to build c:
>>> c = [d | b_supporters.get(d['supporterId'], {}) for d in a]
producing:
>>> c
[{'name': 'John', 'supporterId': 1}, {'name': 'Paul', 'supporterId': 2, 'dependent': 'Anna', 'email': 'ana#gmail.com'}]
I think this solves your problem:
c = []
for i, j in enumerate(a):
c.append(j)
c[i]['data'] = []
for k in b:
if j['supporterId'] == k['supporterId']:
c[i]['data'].append(k)
if not c[i]['data']:
del c[i]['data']
print(c)
Output:
[{'name': 'John', 'supporterId': 1}, {'name': 'Paul', 'supporterId': 2, 'data': [{'dependent': 'Erick', 'supporterId': 2, 'email': 'erick#gmail.com'}, {'dependent': 'Anna', 'supporterId': 2, 'email': 'ana#gmail.com'}]}]
Im trying to add each values of score to the dict names i,e score[0] to names[0] and so on...
names=[{'id': 1, 'name': 'laptop'}, {'id': 2, 'name': 'box'}, {'id': 3, 'name': 'printer'}]
score = [0.9894376397132874, 0.819094657897949, 0.78116521835327]
Output should be like this
names=[{'id': 1, 'name': 'laptop','score':0.98}, {'id': 2, 'name': 'box','score':0.81}, {'id': 3, 'name': 'printer','score':0.78}]
How to achieve this? thanks in advance
I'd do it with a comprehension like this:
>>> [{**d, 'score':s} for d, s in zip(names, score)]
[{'id': 1, 'name': 'laptop', 'score': 0.9894376397132874}, {'id': 2, 'name': 'box', 'score': 0.819094657897949}, {'id': 3, 'name': 'printer', 'score': 0.78116521835327}]
Without list comprehension.
for i, name in enumerate(names):
name['score'] = score[i]
print(names)
This is an easy-to-understand solution. From your example, I understand you don't want to round up the numbers but still want to cut them.
import math
def truncate(f, n):
return math.floor(f * 10 ** n) / 10 ** n
names=[{'id': 1, 'name': 'laptop'}, {'id': 2, 'name': 'box'}, {'id': 3, 'name': 'printer'}]
score = [0.9894376397132874, 0.819094657897949, 0.78116521835327]
n = len(score)
for i in range(n):
names[i]["score"] = truncate(score[i], 2)
print(names)
If you do want to round up the numbers:
names=[{'id': 1, 'name': 'laptop'}, {'id': 2, 'name': 'box'}, {'id': 3, 'name': 'printer'}]
score = [0.9894376397132874, 0.819094657897949, 0.78116521835327]
n = len(score)
for i in range(n):
names[i]["score"] = round(score[i], 2)
print(names)
I have two list with particular data I would like to merge them into a single list with out duplicates.
list1 =[{"id": "123","Name": "Sam", "Age": 10},{"id": "124","Name": "Ajay", "Age": 10}]
list2 =[{"id": "123","Name": "Sam"},{"id": "124","Name": "Ajay"},{"id": "125","Name": "Ram"}]
The output list should be like this
output= [{"id": "123","Name": "Sam", "Age": 10},{"id": "124","Name": "Ajay", "Age": 10},{"id": "125","Name": "Ram"}]
Presumably it is the id key that uniquely identifies the information. If so, collect all the info from the two lists in a dictionary, then produce a new list from that:
from itertools import chain
per_id = {}
for info in chain(list1, list2):
per_id.setdefault(info['id'], {}).update(info)
output = list(per_id.values()) # Python 2 and 3 compatible
Demo:
>>> from itertools import chain
>>> list1 = [{'Age': 10, 'id': '123', 'Name': 'Sam'}, {'Age': 10, 'id': '124', 'Name': 'Ajay'}]
>>> list2 = [{'id': '123', 'Name': 'Sam'}, {'id': '124', 'Name': 'Ajay'}, {'id': '125', 'Name': 'Ram'}]
>>> per_id = {}
>>> for info in chain(list1, list2):
... per_id.setdefault(info['id'], {}).update(info)
...
>>> list(per_id.values())
[{'Age': 10, 'id': '123', 'Name': 'Sam'}, {'Age': 10, 'id': '124', 'Name': 'Ajay'}, {'id': '125', 'Name': 'Ram'}]
l1 = [1, 2, 3]
l2 = ['foo', 'bar', 'test']
z1 = zip(l1,l2)
list(z1)
[(1, 'foo'), (2, 'bar'), (3, 'test')]
That's a sample of my code. Now I want to map (??) each value of the tuples to either id, or name.
So I can get a result like :
[('id':1, 'name':'foo'), ('id':2, 'name':'bar'), ('id':3, 'name':'test')]
What I did is :
>>> result = []
>>> for i in zip(l1,l2):
... d['id'] = i[0]
... d['name'] = i[1]
... result.append(d)
>>> result
[{'id': 3, 'name': 'test'}, {'id': 3, 'name': 'test'}, {'id': 3, 'name': 'test'}]
but 1st) it doesn't works and 2nd) not pythonic at all as far as I can tell...
I don't understand why the loop above doesn't works. If I do :
>>> for i in zip(l1,l2):
... print(i[0], i[1])
...
1 foo
2 bar
3 test
it iterates every item without problem and the append() I used above with the list shouldn't cause any problems...
You can write that for loop pythonically using a dict comprehension:
[{'id': id, 'name': name} for id,name in zip(l1, l2)]
Depending on how complex this dict actually is, and what you want to do with it, you might want to consider using a simple class instead.
Id d is your dictionary what you are doing is replacing the values of the keys(id & name) of the dictionary d and your are appending it to a list.
To create a list of dictionary you can use a list comprehension like
l1 = [1, 2, 3]
l2 = ['foo', 'bar', 'test']
result = [{'id': i[0], 'name':i[1]} for i in zip(l1,l2)]
Your solution doesn't work because you are "overriding" the dict at each step :
>>> for i in zip(l1,l2):
... d['id']=i[0]
... d['name']=i[1]
... r.append(d)
... print r
...
[{'id': 1, 'name': 'foo'}]
[{'id': 2, 'name': 'bar'}, {'id': 2, 'name': 'bar'}]
[{'id': 3, 'name': 'test'}, {'id': 3, 'name': 'test'}, {'id': 3, 'name': 'test'}]
One way to go is to "reset" your dict at the beginning of each step:
>>> for i in zip(l1,l2):
... d={}
... d['id']=i[0]
... d['name']=i[1]
... r.append(d)
... print r
...
[{'id': 1, 'name': 'foo'}]
[{'id': 1, 'name': 'foo'}, {'id': 2, 'name': 'bar'}]
[{'id': 1, 'name': 'foo'}, {'id': 2, 'name': 'bar'}, {'id': 3, 'name': 'test'}]
But as others pointed out, [{'id': id, 'name': name} for id, name in zip(l1, l2)] is more pythonic.
And I don't know if you could use it, but you could build your dict from your zip:
>>> dict(zip(l1, l2))
{1: 'foo', 2: 'bar', 3: 'test'}
I have the following two ValueQuerySets from Django.
dict1 = [{'user': 1, 'total_bookmarked': 2}, {'user': 2, 'total_bookmarked': 3}]
dict2 = [{'user': 1, 'name': 'Joe'}, {'user': 2, 'name': 'Paula'}]
How can I merge the two ValueQuerySet so that I can get the following:
dict3 = [{'user': 1, 'name': 'Joe', 'total_bookmarked':2}, {'user': 2, 'name': 'Paula', 'total_bookmarked': 3}]
How would I do this? I have thought about converting these back into a Python list of dictionaries, but I'm not sure exactly how to approach it even it that works.
I would first suggest you try to see if you can get this in one query because its more efficient. But if you want to update the first list with the second list, and they are both in the same order:
list1 = [{'user': 1, 'total_bookmarked': 2}, {'user': 2, 'total_bookmarked': 3}]
list2 = [{'user': 1, 'name': 'Joe'}, {'user': 2, 'name': 'Paula'}]
for a,b in zip(list1, list2):
a.update(b)
You can further improve the efficiency if they are very large lists by using izip
from itertools import izip
for a,b in izip(list1, list2):
a.update(b)
And if for some reason they are not both already sorted by user:
from operator import itemgetter
list1.sort(key=itemgetter('user'))
list2.sort(key=itemgetter('user'))
I would avoid a solution that uses nested for-loops, as it won't be as efficient.
If they were just unordered lists or dictionaries it would be
list1 = [{'user': 1, 'total_bookmarked': 2}, {'user': 2, 'total_bookmarked': 3}]
list2 = [{'user': 1, 'name': 'Joe'}, {'user': 2, 'name': 'Paula'}]
list3 = []
for d1 in list1:
for d2 in list2:
if d1['user'] == d2['user']:
d3 = dict(d1.items()+d2.items()
list3.append(d3)
break
else:
continue
There is a much better way if your lists are ordered by user
list1 = [{'user': 1, 'total_bookmarked': 2}, {'user': 2, 'total_bookmarked': 3}]
list2 = [{'user': 1, 'name': 'Joe'}, {'user': 2, 'name': 'Paula'}]
list3 = [dict(d1.items()+d2.items()) for (d1, d2) in zip(list1,list2)]