Append, Remove, Edit a Dictionary Item from List of Dictionary - python

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'}]

Related

How to "flatten" list of dictionaries in python

I have a list of dictionaries that looks like this:
test_dict = [{'id': 0, 'name': ['Jim'], 'lastname': ['kkk']}, {'id': 1, 'name': ['John'], 'lastname': ['lll']}]
test_dict
[{'id': 0, 'name': ['Jim'], 'lastname': ['kkk']},
{'id': 1, 'name': ['John'], 'lastname': ['lll']}]
I would like to create another dictionary that will have as keys, the ids of the test_dict.
The output I am looking for, looks like this:
test_dict_f = {'0': {'name': ['Jim'], 'lastname': ['kkk']},
'1': {'name': ['John'], 'lastname': ['lll']}}
test_dict_f
{'0': {'name': ['Jim'], 'lastname': ['kkk']},
'1': {'name': ['John'], 'lastname': ['lll']}}
Any ideas how I could achieve this ?
Try this in one line:
result = {str(i["id"]): {"name": i["name"], "lastname": i["lastname"]} for i in test_dict}
the result will be:
{'0': {'name': ['Jim'], 'lastname': ['kkk']},
'1': {'name': ['John'], 'lastname': ['lll']}}
Here's another way to do it that doesn't rely on knowledge of any keys other than 'id'. Note that this is destructive:
test_dict = [{'id': 0, 'name': ['Jim'], 'lastname': ['kkk']}, {'id': 1, 'name': ['John'], 'lastname': ['lll']}]
test_dict_f = {}
for d in test_dict:
id_ = d.pop('id')
test_dict_f[str(id_)] = d
print(test_dict_f)
Output:
{'0': {'name': ['Jim'], 'lastname': ['kkk']}, '1': {'name': ['John'], 'lastname': ['lll']}}
test_dict = [{'id': 0, 'name': ['Jim'], 'lastname': ['kkk']}, {'id': 1, 'name': ['John'], 'lastname': ['lll']}]
pp({i["id"]: {k:v for k,v in i.items() if k!="id"} for i in test_dict})
or event much funnier:
pp({i["id"]: i|{"id":i["id"]} for i in test_dict})
{0: {'name': ['Jim'], 'lastname': ['kkk']},
1: {'name': ['John'], 'lastname': ['lll']}}

Merge two list in python

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'}

Python: Search for a list of nested dict in a list of nested dict

Let's say we have:
stack = [
{'id': '1', 'name': {'firstname': 'bob', 'lastname': 'smith'}},
{'id': '2', 'name': {'firstname': 'jane', 'lastname': 'abb'}},
{'id': '3', 'name': {'firstname': 'flo', 'lastname': 'gram', 'middle': 'remi'}},
{'id': '4', 'name': {'firstname': 'frank', 'lastname': 'glow'}, 'partner': 'diane'}
]
needles = [{'name':{'lastname': 'gram'}},
{'partner': 'diane'}
]
We'd like a function find, like so:
list = find(needles, stack)
print(list)
>[{id: '3', name: {firstname: 'flo', lastname: 'gram', middle: 'remi'}}, {id: '4', name: {firstname: 'frank', lastname: 'glow'}, partner: 'diane'}]
At first I wanted to use items(), like so:
def find(needle, stack):
result = []
for needle in needles:
for item in stack:
if needle.items() <= item.items():
result.append()
But this returns:
[{'id': '4', 'name': {'firstname': 'frank', 'lastname': 'glow'}, 'partner': 'diane'}]
Because the item match has to be exact, I would have to pass ['name': {'firstname': 'flo', 'lastname': 'gram', 'middle': 'remi'}, {'partner': 'diane'}' for my function to return the desired result.
I am not sure where to go from here. Since my stack can be nested for an unknown depth ({a:{b:{c:value}}}) the solution might be some sort of recursion but it might not be necessary since I want to check for the exact 'path' (keys) in needle. It comes down to partially match needle items with stack items.
You can use recursion:
def find(n, s):
def exists(n, d):
if type(n) != type(d):
return False
if not isinstance(n, (dict, list)):
return n == d
if isinstance(n, list):
return any(exists(j, k) for j in n for k in d)
return all(exists(b, d.get(a, None)) for a, b in n.items())
return [i for i in s if any(exists(j, i) for j in n)]
stack = [{'id': '1', 'name': {'firstname': 'bob', 'lastname': 'smith'}}, {'id': '2', 'name': {'firstname': 'jane', 'lastname': 'abb'}}, {'id': '3', 'name': {'firstname': 'flo', 'lastname': 'gram', 'middle': 'remi'}}, {'id': '4', 'name': {'firstname': 'frank', 'lastname': 'glow'}, 'partner': 'diane'}, {'id': '5', 'name': {'firstname': ['flo', 'Flo'], 'lastname': 'gram', 'middle': 'remi'}}]
needles = [{'name': {'lastname': 'gram'}}, {'partner': 'diane'}, {'name':{'firstname':['Flo']}}]
results = find(needles, stack)
Output:
[{'id': '3', 'name': {'firstname': 'flo', 'lastname': 'gram', 'middle': 'remi'}},
{'id': '4', 'name': {'firstname': 'frank', 'lastname': 'glow'}, 'partner': 'diane'},
{'id': '5', 'name': {'firstname': ['flo', 'Flo'], 'lastname': 'gram', 'middle': 'remi'}}]

Extract dict value from list of dict in python

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]

Using pandas to add list of dicts together

This is a follow-up to this question: Using pandas to add list elements together. I would like to generalize this function to getting unique elements in an array, even if they're not of a 'hashable' type, such as a dict. Here is the input array:
items = [
{
'FirstName': 'David',
'LastName': 'Smith',
'Residence': [{'Place': 'X', 'Age': 22}, {'Place': 'Y', 'Age': 23}]
},
{
'FirstName': 'David',
'LastName': 'Smith',
'Residence': [{'Place': 'Z', 'Age': 20}]
},
{
'FirstName': 'David',
'LastName': 'Smith',
'Residence': [{'Place': 'Z', 'Age': 20}]
},
{
'FirstName': 'Bob',
'LastName': 'Jones',
'Residence': [{'Place': 'Z', 'Age': 20}]
}
]
I want to add together the unique Residences (dicts) together, so the final result would be:
items = [
{
'FirstName': 'David',
'LastName': 'Smith',
'Residence': [{'Place': 'X', 'Age': 22}, {'Place': 'Y', 'Age': 23}, {'Place': 'Z', 'Age': 20}]
},
{
'FirstName': 'Bob',
'LastName': 'Jones',
'Residence': [{'Place': 'Z', 'Age': 20}]
}
]
The SQL I would use would be something like this:
SELECT FirstName, LastName, GROUP_CONCAT(DISTINCT **Residence Object**)
FROM items
GROUP BY FirstName, LastName
How would I do this in pandas, so that I don't get an unhashable type error when trying to get the distinct array elements?
Barring anything else, I don't think Pandas would give you any real benefit here:
from collections import defaultdict
d = defaultdict(list)
for e in items:
d[(e['FirstName'], e['LastName'])].append(e['Residence'])
items = [{'FirstName': k[0], 'LastName': k[1], 'Residence': v} for k, v in d.items()]
Solution from pandas
#df=pd.DataFrame(items)
df.groupby(['FirstName','LastName']).Residence.\
apply(lambda x : x.sum()).\
apply(lambda x : [dict(y) for y in set(tuple(t.items()) for t in x)]).\
reset_index().to_dict('r')
Out[104]:
[{'FirstName': 'Bob',
'LastName': 'Jones',
'Residence': [{'Age': 20, 'Place': 'Z'}]},
{'FirstName': 'David',
'LastName': 'Smith',
'Residence': [{'Age': 20, 'Place': 'Z'},
{'Age': 23, 'Place': 'Y'},
{'Age': 22, 'Place': 'X'}]}]

Categories

Resources