Dict list comprehension in Python - python-3.x

I am a python newbie. I am trying to learn comprehension and I am stuck currently with the scenario. I am able to do this mutation
sample_dict_list = [{'name': 'Vijay', 'age':30, 'empId': 1}, {'name': 'VV', 'age': 10, 'empId': 2},
{'name': 'VV1', 'age': 40, 'empId': 3}, {'name': 'VV2', 'age': 20, 'empId': 4}]
def list_mutate_dict(list1, mutable_func):
for items in list1:
for key,value in items.items():
if(key == 'age'):
items[key] = mutable_func(value)
return
mutable_list_func = lambda data: data*10
list_mutate_dict(sample_dict_list, mutable_list_func)
print(sample_dict_list)
[{'name': 'Vijay', 'age': 300, 'empId': 1}, {'name': 'VV', 'age': 100, 'empId': 2}, {'name': 'VV1', 'age': 400, 'empId': 3}, {'name': 'VV2', 'age': 200, 'empId': 4}]
Dict with key 'age' alone is mutated and returned
THis works fine. But I am trying the same with the single line comprehension. I am unsure if it can be done.
print([item for key,value in item.items() if (key == 'age') mutable_list_func(value) for item in sample_dict_list])
THis is the op - [{'age': 200}, {'age': 200}, {'age': 200}, {'age': 200}] which is incorrect. It just takes in the last value and mutates and returns as a dict list
Could this be done in a "nested" list dict comprehension?

When using comprehensions, you are actually creating a new one so "mutating" falls outside the context. But assuming you want the same output:
mutable_func = lambda data: data*10
print([{**d, "age": mutable_func(d["age"])} for d in sample_dict_list])
In my example you are unpacking the dictionary with **d and adding another key-value which overwrites the existing one in d.

It's a bit complicated but here:
def list_mutate_dict(list1, mutable_func):
[{key: (mutable_func(value) if key == 'age' else value) for key, value in item.items()} for item in list1]
Explanation (going inside out):
First, you mutate the value if needed in the condition inside the assignment, keeping all other values the same.
Then, you do this for all dictionary items by iterating all the items.
And, finally, you do this for all dictionaries in the list.
I will add a caveat that these types of list comprehensions are not considered a best practice and often lead to very confusing and unmaintainable code.

Related

Sort a list of dictionaries by keys in Python

I have a list of dictionary like this [{1: {'Name': 't1', 'seq': 1}}, {3: {'Name': 't3', 'seq': 3}}, {2: {'Name': 't2', 'seq': 2}}]
And I want to sort this list based on just the key (and not the value of that key)
Expected output is
[{1: {'Name': 't1', 'seq': 1}}, {2: {'Name': 't3', 'seq': 2}}, {3: {'Name': 't2', 'seq': 3}}]
I know this can be done by getting key as list then sort them and then create another list, but i am looking for more elegant may be a one liner solution
You can use the key arg at sorted that gets a function to sort
docs: https://docs.python.org/3/library/functions.html#sorted
sorted_lst = sorted(lst, key=lambda x: list(x.keys())[0])

How to add key and value pairs to new empty dictionary using for loop?

So I am trying to create a new dictionary from a list with dictionary values.
debts_list = [{'amount': 123.46, 'id': 0}, {'amount': 100, 'id': 1}, {'amount': 4920.34, 'id': 2}, {'amount': 12938, 'id': 3}, {'amount': 9238.02, 'id': 4}]
Here is my for loop.
new_debt_dic = {}
for i in debts_list:
for k, v in i.items():
new_debt_dic[k] = v
Problem here is that I'm only getting the last key and value added. Output is {'amount': 9238.02, 'id': 4} when I want to get all the values. I tried using setdefault but it doesn't seem to work the way I want it to. What other libraries/solutions can this be solved with?
In Python, dictionary keys are unique. If you assign a value to the same key again, it gets overwritten. Example :
dct = {}
dct["key"] = "value"
print(dct)
dct["key"] = "value2"
print(dct)
Output :
{"key": "value"}
{"key": "value2"}
The only option you have is to create a list of amounts and a list of ids:
new_debt_dic = {"amounts": [], "ids": []}
for i in debts_list:
new_debt_dic["amounts"].append(i["amount"])
new_debt_dic["ids"].append(i["id"])
print(new_debt_dic)
Output :
{"amounts": [123.46, 100, ...], "ids": [0, 1, ...]}
Each value of debts_list is dictionary with only 2 key-value pairs, where the keys are amount or id. I think you meant to use the id as your keys - if so, you should use the following:
new_debt_dic = {}
for d in debts_list:
new_debt_dic[d['id']] = d['amount']

Is there some way to reform construction in ptyhon's list and dic?

here is a list:
test=[
{'name':'David','money':10},
{'name':'David','money':20},
{'name':'Scart','money':50},
]
I want to reform test to this:
result=[
{'name':David,'money':30,'count':2},
{'name':Scart,'money':50,'count':1}
]
the test'length may be 500+,thanks a lot!
Here's you test list.
>>> test=[
... {'name':'David','money':10},
... {'name':'David','money':20},
... {'name':'Scart','money':50},
... ]
You can first build a dict mapping names to amounts of money
>>> amounts_by_name = {}
>>> for d in test:
... amounts_by_name.setdefault(d['name'], []).append(d['money'])
...
(The setdefault creates the (d[name], []) entry if it does not exists.) The amounts are appended to the list:
>>> amounts_by_name
{'David': [10, 20], 'Scart': [50]}
Now, you can turn the dict into a list:
>>> [{'name': name, 'money': sum(amounts), 'count': len(amounts)} for name, amounts in amounts_by_name.items()]
[{'name': 'David', 'money': 30, 'count': 2}, {'name': 'Scart', 'money': 50, 'count': 1}]

Python list of dictionaries search with multiple input

Sorry for such a stupid question but im on deadend right now (1st time using python), how do i search Python list of dictionaries with multiple
attribute ?
My current code is only can search by 1 attribute.
people = [{'name': 'Alex', 'age': '19',
'grade': 80},
{'name': 'Brian', 'age': '17', 'grade':
90},
{'name': 'Junior', 'age': '17', 'grade':
90},
{'name': 'Zoey', 'age': '19', 'grade':
95},
{'name': 'joe', 'age': '18', 'grade':
90}]
entry=input("Check the name you want to search the grade :")
list(filter(lambda person: person['name'] == entry, people))
I want it to search by multitple attribute, so if i input either '17' or 90, the expected output is
[{'name': 'Brian', 'age': '17', 'grade': 90},
{'name': 'Junior', 'age': '17', 'grade': 90}]
You could just use two conditions connected by an or (while taking measures not to compare strings with numbers):
list(filter(lambda person: str(person['grade']) == entry or str(person['grade']) == entry, people))
At some point, a comprehension will be more readable:
[p for p in people if str(person['grade']) == entry or str(p['grade']) == entry]
And if you want to add more search keys, you can further DRY this out, using any:
keys = ('name', 'grade', 'age')
filtered = [p for p in people if any(str(p[k]) == entry for k in keys)]

Filtering out the values of inner dictionary in Python

I have dictionary,
dict={
{'dept': 'ECE', 'id': 1, 'name': 'asif', 'City': 'Bangalore'},
{'dept': 'ECE', 'id': 2, 'name': 'iqbal', 'City': 'Kolkata'}
}
I wanted to is there any way so that I can filter out the name and dept on the basis of City?
I tried but couldn't find any way out.
Ok, If I understand your question, and from the fact that set has been converted to a list, I think something like that could be what you are looking for:
data=[
{'dept': 'ECE', 'id': 1, 'name': 'asif', 'City': 'Bangalore'},
{'dept': 'ECE', 'id': 2, 'name': 'iqbal', 'City': 'Kolkata'},
]
my_keys = ('name','dept',)
my_cities = ['Kolkata',]
my_dicts = [{key:value for key, value in dictionary.items() if key in my_keys} for dictionary in data if dictionary['City'] in my_cities]
print(my_dicts)

Resources