i have a simple task but not able to figure it out.
a = [{'name': 'Helen', 'age': '12', 'total_money':'12000'}, {'name': 'Victor', 'age':'20', 'total_money': '32999'}]
b = [{'name': 'Helen', 'age': '12', 'total_gold':'14'}]
I want to mere to list above, if the value of name and ageis the same then combine it together. if not the same then leave it as it is.
expected output
output = [{'name': 'Helen', 'age': '12', 'total_money':'12000', 'total_gold':'14'}, {'name': 'Victor', 'age':'20', 'total_money': '32999'}]
this is what i have tried so far (not working)
c = a + b
data = {}
for item in c:
key = item["name"]+'-'+item["age"]
if key in data:
if data[key]["total_money"] in data[key]:
data[key]["total_gold"] = item["total_gold"]
else:
data[key]["total_money"] = item["total_money"]
else:
data[key] = item
data[key]["total_money"] = item['total_money'] if 'total_money' in item else 0
data[key]["total_gold"] = item['total_gold'] if 'total_gold' in item else 0
i have a feeling that i am overthinking. any suggestion would be appreciate. Thank you.
Seems like you want to merge two dictionaries, which can be done like so:
a = {'name': 'Helen', 'age': '12', 'total_money':'12000'}
b = {'name': 'Helen', 'age': '12', 'total_gold':'14'}
z = {**a, **b}
z
{'name': 'Helen', 'age': '12', 'total_money': '12000', 'total_gold': '14'}
If you'd like to maintain the list structure (assuming you plan to have multiple dictionaries as elements of these lists):
a = [{'name': 'Helen', 'age': '12', 'total_money':'12000'}]
b = [{'name': 'Helen', 'age': '12', 'total_gold':'14'}]
z = []
for i in range(len(a)):
z.append({**a[i], **b[i]})
EDIT:
z = []
for ele in a:
for piece in b:
if ele["name"] == piece["name"] and ele["age"] == piece["age"]:
z.append({**ele, **piece})
else:
z.append(ele)
Solution
This is a good opportunity to learn how to use itertools.groupby():
import itertools
def sort_help(d: dict) -> tuple:
return d["name"], d["age"]
merged = []
for _, group in itertools.groupby(sorted(a + b, key=sort_help), key=sort_help):
merged_dict = {}
for d in group:
merged_dict.update(d)
merged.append(merged_dict)
Output:
[{'name': 'Helen', 'age': '12', 'total_money': '12000', 'total_gold': '14'},
{'name': 'Victor', 'age': '20', 'total_money': '32999'}]
Explanation
This works by first concatenating your lists of dictionaries, and then sorting them by name, age tuples:
In [6]: a + b
Out[6]:
[{'name': 'Helen', 'age': '12', 'total_money': '12000'},
{'name': 'Victor', 'age': '20', 'total_money': '32999'},
{'name': 'Helen', 'age': '12', 'total_gold': '14'}]
In [7]: both_in_order = sorted(a + b, key=sort_help)
In [8]: both_in_order
Out[8]:
[{'name': 'Helen', 'age': '12', 'total_money': '12000'},
{'name': 'Helen', 'age': '12', 'total_gold': '14'},
{'name': 'Victor', 'age': '20', 'total_money': '32999'}]
Then groupby groups the dictionaries into groups of matching name, age tuples:
In [9]: for _, g in itertools.groupby(both_in_order, key=sort_help):
...: print(list(g))
...:
[{'name': 'Helen', 'age': '12', 'total_money': '12000'}, {'name': 'Helen', 'age': '12', 'total_gold': '14'}]
[{'name': 'Victor', 'age': '20', 'total_money': '32999'}]
From there, each group's dictionaries are merged into one.
Advantages
This method also has the benefit of being "extensible"; you could add more criteria for what dictionaries should merge by simply modifying the sort_help function:
[{'name': 'Victor', 'age': 30, 'occupation': 'farmer', 'total_money': 1871},
{'name': 'Helen', 'age': 30, 'occupation': 'adventurer', 'total_gold': 8026},
{'name': 'Helen', 'age': 30, 'occupation': 'farmer', 'total_money': 7279},
{'name': 'Victor', 'age': 20, 'occupation': 'farmer', 'total_gold': 9762},
{'name': 'Victor', 'age': 20, 'occupation': 'farmer', 'total_money': 2853},
{'name': 'Helen', 'age': 30, 'occupation': 'adventurer', 'total_gold': 6002},
{'name': 'Victor', 'age': 20, 'occupation': 'farmer', 'total_gold': 582},
{'name': 'Helen', 'age': 30, 'occupation': 'adventurer', 'total_money': 8632},
{'name': 'Victor', 'age': 30, 'occupation': 'adventurer', 'total_gold': 6528},
{'name': 'Helen', 'age': 30, 'occupation': 'adventurer', 'total_money': 4101}]
By adding "occupation" to sort_help(), we can very easily now group the dictionaries by all three criteria:
def sort_help(d: dict) -> tuple:
return d["name"], d["age"], d["occupation"]
Output:
[{'name': 'Helen', 'age': 30, 'occupation': 'adventurer', 'total_money': 4101, 'total_gold': 8026},
{'name': 'Helen', 'age': 30, 'occupation': 'farmer', 'total_money': 7279},
{'name': 'Victor', 'age': 20, 'occupation': 'farmer', 'total_gold': 9762, 'total_money': 2853},
{'name': 'Victor', 'age': 30, 'occupation': 'adventurer', 'total_gold': 6528},
{'name': 'Victor', 'age': 30, 'occupation': 'farmer', 'total_money': 1871}]
You can also very easily come up with a custom merging function which would, for example, add total_money instead of overwrite.
I re-wrote your function:
for item in c:
key = item["name"]+'-'+item["age"]
if key not in data:
data[key] = item
if "total_gold" in item:
data[key]["total_gold"] = item["total_gold"]
if "total_money" in item:
data[key]["total_money"] = item["total_money"]
if total_gold or total_money is written twice for the same "key" is will user the last value
output: [{'name': 'Helen', 'age': '12', 'total_money': '12000', 'total_gold': '14'}, {'name': 'Victor', 'age': '20', 'total_money': '32999'}]
just iterate over the dictionaries, creating a new dictionary with the values. if the value is a dup it will continue:
a = {'name': 'Helen', 'age': '12', 'total_money':'12000'}
b = {'name': 'Helen', 'age': '12', 'total_gold':'14'}
c={}
for k,v in a.items():
c[k]=v
for k,v in b.items():
c[k]=v
print(c)
#{'name': 'Helen', 'age': '12', 'total_money': '12000', 'total_gold': '14'}
Related
This question already has answers here:
filtering dictionary based on value in a key [duplicate]
(2 answers)
Closed 2 years ago.
I would like to filter the dictionary that has 'hometown':'NY'
[{'name': 'paul', 'age': '26', 'hometown': '98_street_AU', 'gender': 'male'},
{'name': 'mei', 'age': '27', 'hometown': '19_street_NY', 'gender': 'female'},
{'name': 'smith', 'age': '14', 'hometown': '7_street_NY', 'gender': 'male'},
{'name': 'raj', 'age': '13', 'hometown': '56_street_IND', 'gender': 'male'},.....]
here is my code to filter the dictionary and the output
a=[]
for test in result:
x={}
for key,value in test.items():
if key == 'hometown':
if 'NY' in value:
x[key] = value
a.append(x)
print(a)
[{}, {'hometown': '19_street_NY'}, {'hometown': '7_street_NY'}, {}]
my desired output is
[{'name': 'mei', 'age': '27', 'hometown': '19_street_NY', 'gender': 'female'},
{'name': 'smith', 'age': '14', 'hometown': '7_street_NY', 'gender': 'male'}]
Try this simple method:
a=[]
for i in result:
if i['hometown'].__contains__("NY"):
a.append(i)
print(a)
Using a list comprehension with str.endswith
Ex:
a = [test for test in result if test.get('hometown', "").endswith('NY')]
You are adding only item hometown not the dictionary. This should work:
a=[]
for test in result:
x={}
for key,value in test.items():
if key == 'hometown':
if 'NY' in value:
a.append(test)
print(a)
In [6]: a = [{'name': 'paul', 'age': '26', 'hometown': '98_street_AU', 'gender': 'male'},
...: {'name': 'mei', 'age': '27', 'hometown': '19_street_NY', 'gender': 'female'},
...: {'name': 'smith', 'age': '14', 'hometown': '7_street_NY', 'gender': 'male'},
...: {'name': 'raj', 'age': '13', 'hometown': '56_street_IND', 'gender': 'male'}]
In [7]: [i for i in a if "hometown" in i and i["hometown"].endswith("NY")]
Out[7]:
[{'name': 'mei', 'age': '27', 'hometown': '19_street_NY', 'gender': 'female'},
{'name': 'smith', 'age': '14', 'hometown': '7_street_NY', 'gender': 'male'}]
I have a list of dicts like this:
[{'name': 'John', 'age': 25}, {'name': 'Matt', 'age': 35} , {'name': 'Peter', 'age': 40}]
How can I get the name for those whose age is between 20-30 ?
Many thanks for your help.
You would use something like this:
dicta = {'name': 'John', 'age': 25}, {'name': 'Matt', 'age': 35} , {'name': 'Peter', 'age': 40}
for val in dicta:
if 20 <= val['age'] <= 30:
print(val['name'])
You seem to be new to Python so I suggest you look at some tutorials for example like this one on TutorialsPoint. Walks you through dictionaries.
Something like this should do it:
list_of_dicts = [{'name': 'John', 'age': 25}, {'name': 'Matt', 'age': 35} , {'name': 'Peter', 'age': 40}]
names = [d['name'] for d in list_of_dicts if 20 <= d['age'] <= 30]
How can I convert a pandas dataframe to a dict using unique column values as the keys for the dictionary? In this case I want to use unique username's as the key.
Here is my progress so far based on information found on here and online.
My test dataframe:
import pandas
import pprint
df = pandas.DataFrame({
'username': ['Kevin', 'John', 'Kevin', 'John', 'Leslie', 'John'],
'sport': ['Soccer', 'Football', 'Racing', 'Tennis', 'Baseball', 'Bowling'],
'age': ['51','32','20','19','34','27'],
'team': ['Cowboyws', 'Packers', 'Sonics', 'Raiders', 'Wolves', 'Lakers']
})
I can create a dictionary by doing this:
dct = df.to_dict(orient='records')
pprint.pprint(dct, indent=4)
>>>>[{'age': '51', 'sport': 'Soccer', 'team': 'Cowboyws', 'username': 'Kevin'},
{'age': '32', 'sport': 'Football', 'team': 'Packers', 'username': 'John'},
{'age': '20', 'sport': 'Racing', 'team': 'Sonics', 'username': 'Kevin'},
{'age': '19', 'sport': 'Tennis', 'team': 'Raiders', 'username': 'John'},
{'age': '34', 'sport': 'Baseball', 'team': 'Wolves', 'username': 'Leslie'},
{'age': '27', 'sport': 'Bowling', 'team': 'Lakers', 'username': 'John'}]
I tried using the groupby and apply method which got me closer but it converts all the values to lists. I want them to remain as dictionaries so i can retain the each value's key:
result = df.groupby('username').apply(lambda x: x.values.tolist()).to_dict()
pprint.pprint(result, indent=4)
{ 'John': [ ['32', 'Football', 'Packers', 'John'],
['19', 'Tennis', 'Raiders', 'John'],
['27', 'Bowling', 'Lakers', 'John']],
'Kevin': [ ['51', 'Soccer', 'Cowboyws', 'Kevin'],
['20', 'Racing', 'Sonics', 'Kevin']],
'Leslie': [['34', 'Baseball', 'Wolves', 'Leslie']]}
This is the desired result I want:
{
'John': [{'age': '32', 'sport': 'Football', 'team': 'Packers', 'username': 'John'},
{'age': '19', 'sport': 'Tennis', 'team': 'Raiders', 'username': 'John'},
{'age': '27', 'sport': 'Bowling', 'team': 'Lakers', 'username': 'John'}],
'Kevin': [{'age': '51', 'sport': 'Soccer', 'team': 'Cowboyws', 'username': 'Kevin'},
{'age': '20', 'sport': 'Racing', 'team': 'Sonics', 'username': 'Kevin'}],
'Leslie': [{'age': '34', 'sport': 'Baseball', 'team': 'Wolves', 'username': 'Leslie'}]
}
Use groupby and apply. Inside the apply, call to_dict with the "records" orient (similar to what you've figured out already).
df.groupby('username').apply(lambda x: x.to_dict(orient='r')).to_dict()
I prefer using for loop here , also you may want to drop the username columns , since it is redundant
d = {x: y.drop('username',1).to_dict('r') for x , y in df.groupby('username')}
d
Out[212]:
{'John': [{'age': '32', 'sport': 'Football', 'team': 'Packers'},
{'age': '19', 'sport': 'Tennis', 'team': 'Raiders'},
{'age': '27', 'sport': 'Bowling', 'team': 'Lakers'}],
'Kevin': [{'age': '51', 'sport': 'Soccer', 'team': 'Cowboyws'},
{'age': '20', 'sport': 'Racing', 'team': 'Sonics'}],
'Leslie': [{'age': '34', 'sport': 'Baseball', 'team': 'Wolves'}]}
I have a sorted list based on the value for key name as below:
s = [{'name': 'Bart', 'age': 12}, {'name': 'Bart', 'age': 19}, {'name': 'Bart', 'age': 1},{'name': 'Homer', 'age': 30}, {'name': 'Homer', 'age': 12},{'name': 'Simpson', 'age': 19}]
I want to arrange the elements of the list such that dictionaries with the same value for key name do not occur one after the other.
Required output:
[{'name': 'Bart', 'age': 12}, {'name': 'Homer', 'age': 30}, {'name': 'Simpson', 'age': 19}, {'name': 'Bart', 'age': 19}, {'name': 'Homer', 'age': 12}, {'name': 'Bart', 'age': 1}]
OR
[{'name': 'Bart', 'age': 12}, {'name': 'Homer', 'age': 30}, {'name': 'Bart', 'age': 19}, {'name': 'Homer', 'age': 12}, {'name': 'Bart', 'age': 1},{'name': 'Simpson', 'age': 19}]
To get either one of the required outputs I tried using map and lambda
The idea was to compare every name element with the next elements name and if they don't match, swap the values and return the resulting list.
Below is the code which I was trying:
map(lambda x: x if x['name']!=next(iter(x))['name'] else None, s)
One thing that did not work is that next(iter(x) did not return the next element. I also want to know why and if the solution can be achieved using map and lambda ?
I wrote this according to your requirements, though it is not as condensed:
s = [{'name': 'Bart', 'age': 12}, {'name': 'Bart', 'age': 19}, {'name': 'Bart', 'age': 1},
{'name': 'Homer', 'age': 30}, {'name': 'Homer', 'age': 12},{'name': 'Simpson', 'age': 19}]
res=[]
for m,n in zip(s, reversed(s)):
if m!=n:
res.append(m)
res.append(n)
else:
res.append(m)
if len(res)==len(s):
break
print res
It makes use of the fact that you already have the sorted list.
How do I perform such task in a list of dictionary?
lists = [{'firstname': 'John', 'lastname': 'Doe', 'color': 'red'}]
(1) Append an item, {'age': '30'} to the current lists [0].
lists = [{'firstname': 'John', 'lastname': 'Doe', 'color': 'red', 'age': '30}]
(2) How do I change the 'lastname' to 'Smith'?
lists = [{'firstname': 'John', 'lastname': 'Smith', 'color': 'red', 'age': '30}]
(3) How do I remove the 'color' from the list?
lists = [{'firstname': 'John', 'lastname': 'Smith', 'age': '30}]
lists = [{'firstname': 'John', 'lastname': 'Doe', 'color': 'red'}]
# update value to 30
lists[0]["age"] = 30
print(lists)
# update value to smith
lists[0]["lastname"] = "Smith"
print(lists)
# finally delete using the del statement using the key
del lists[0]["color"]
print(lists)
[{'firstname': 'John', 'lastname': 'Doe', 'age': 30, 'color': 'red'}]
[{'firstname': 'John', 'lastname': 'Smith', 'age': 30, 'color': 'red'}]
[{'firstname': 'John', 'lastname': 'Smith', 'age': 30}]
The same way you would with any other dictionary. lists[0] is a dictionary.
(1) Appending:
lists[0]['age'] = '30'
(2) Modifying
lists[0]['lastname'] = 'Smith'
(3) Deleting
del lists[0]['color']
(1) Append an item, {'age': '30'} to the current lists [0].
>>>lists[0]['age']=30
>>>lists
[{'age': 30, 'color': 'red', 'firstname': 'John', 'lastname': 'Doe'}]
(2) How do I change the 'lastname' to 'Smith'?
>>>lists[0]['lastname'] = "Smith"
>>>lists
[{'lastname': 'Smith', 'age': 30, 'color': 'red', 'firstname': 'John'}]
(3) How do I remove the 'color' from the list?
>>>del lists[0]['color'] #or lists[0].pop('color') , This should return `red`
>>>lists
[{'lastname': 'Smith', 'age': 30, 'firstname': 'John'}]