Python: updating priorities in a list of dictionaries
Question:
I have the following list of dictionaries:
tasks = [{'priority': 2, 'task': 'math', 'complete_time': 15},
{'priority': 10, 'task': 'french', 'complete_time': 90},
{'priority': 5, 'task': 'geography', 'complete_time': 45},
{'priority': 2, 'task': 'math', 'complete_time': 100}]
I would like to update this list by changing the priorities from zero ongoing so that I get:
[
{'priority':0, 'task':'math', 'complete_time': 15},
{'priority':0, 'task':'math', 'complete_time': 100},
{'priority':1, 'task':'geography', 'complete_time': 45},
{'priority':2, 'task':'french', 'complete_time': 90},
]
I have started by listing the set of all possible priority values:
tasks_set = list({x['priority']:x for x in tasks}.values())
which gives:
[{'priority': 2, 'task': 'math', 'complete_time': 100},
{'priority': 10, 'task': 'french', 'complete_time': 90},
{'priority': 5, 'task': 'geography', 'complete_time': 45}]
but am stuck after this!
Answers:
This is one simple solution:
from pprint import pprint
tasks = [
{'priority': 2, 'task': 'math', 'complete_time': 15},
{'priority': 10, 'task': 'french', 'complete_time': 90},
{'priority': 5, 'task': 'geography', 'complete_time': 45},
{'priority': 2, 'task': 'math', 'complete_time': 100}
]
priority_set = list(sorted({task["priority"] for task in tasks}))
priorities_updater = {}
for i in range(len(priority_set)):
priorities_updater[priority_set[i]] = i
for i in range(len(tasks)):
tasks[i]["priority"] = priorities_updater[tasks[i]["priority"]]
pprint(tasks)
# output
# [{'complete_time': 15, 'priority': 0, 'task': 'math'},
# {'complete_time': 90, 'priority': 2, 'task': 'french'},
# {'complete_time': 45, 'priority': 1, 'task': 'geography'},
# {'complete_time': 100, 'priority': 0, 'task': 'math'}]
You may observe that the priority
attribute in the tasks is no longer the first one in the set, this is normal for Python set
s, which are un-ordered (contrary to the list
s), and for which the default behavior is then to sort the keys by alphabetical order.
Here we first build a set with all the priorities using set comprehension ({task["priority"] for task in tasks}
). Then we sort the values for them to be in ascending order. Finally, we convert the set to a list (not really necessary here, but a habit I’ve taken if the indices of the elements are significant).
When this is done, we build a dictionary in which the keys are the old priorities, while the values are the new ones.
Finally, we go through the tasks
dictionary and update the priorities.
You can use it "sorted" function, you don’t need to casting for set type;
from pprint import pp
tasks = [{'priority': 2, 'task': 'math', 'complete_time': 15},
{'priority': 10, 'task': 'french', 'complete_time': 90},
{'priority': 5, 'task': 'geography', 'complete_time': 45},
{'priority': 2, 'task': 'math', 'complete_time': 100}]
sorted_task = sorted(tasks, key=lambda val: val['priority'])
for order, task in enumerate(sorted_task):
task['priority'] = order
pp(sorted_task)
# output:
# [{'priority': 0, 'task': 'math', 'complete_time': 15},
# {'priority': 1, 'task': 'math', 'complete_time': 100},
# {'priority': 2, 'task': 'geography', 'complete_time': 45},
# {'priority': 3, 'task': 'french', 'complete_time': 90}]
If you want to sort by reverse, just add "reverse=True" parameter.
I have the following list of dictionaries:
tasks = [{'priority': 2, 'task': 'math', 'complete_time': 15},
{'priority': 10, 'task': 'french', 'complete_time': 90},
{'priority': 5, 'task': 'geography', 'complete_time': 45},
{'priority': 2, 'task': 'math', 'complete_time': 100}]
I would like to update this list by changing the priorities from zero ongoing so that I get:
[
{'priority':0, 'task':'math', 'complete_time': 15},
{'priority':0, 'task':'math', 'complete_time': 100},
{'priority':1, 'task':'geography', 'complete_time': 45},
{'priority':2, 'task':'french', 'complete_time': 90},
]
I have started by listing the set of all possible priority values:
tasks_set = list({x['priority']:x for x in tasks}.values())
which gives:
[{'priority': 2, 'task': 'math', 'complete_time': 100},
{'priority': 10, 'task': 'french', 'complete_time': 90},
{'priority': 5, 'task': 'geography', 'complete_time': 45}]
but am stuck after this!
This is one simple solution:
from pprint import pprint
tasks = [
{'priority': 2, 'task': 'math', 'complete_time': 15},
{'priority': 10, 'task': 'french', 'complete_time': 90},
{'priority': 5, 'task': 'geography', 'complete_time': 45},
{'priority': 2, 'task': 'math', 'complete_time': 100}
]
priority_set = list(sorted({task["priority"] for task in tasks}))
priorities_updater = {}
for i in range(len(priority_set)):
priorities_updater[priority_set[i]] = i
for i in range(len(tasks)):
tasks[i]["priority"] = priorities_updater[tasks[i]["priority"]]
pprint(tasks)
# output
# [{'complete_time': 15, 'priority': 0, 'task': 'math'},
# {'complete_time': 90, 'priority': 2, 'task': 'french'},
# {'complete_time': 45, 'priority': 1, 'task': 'geography'},
# {'complete_time': 100, 'priority': 0, 'task': 'math'}]
You may observe that the priority
attribute in the tasks is no longer the first one in the set, this is normal for Python set
s, which are un-ordered (contrary to the list
s), and for which the default behavior is then to sort the keys by alphabetical order.
Here we first build a set with all the priorities using set comprehension ({task["priority"] for task in tasks}
). Then we sort the values for them to be in ascending order. Finally, we convert the set to a list (not really necessary here, but a habit I’ve taken if the indices of the elements are significant).
When this is done, we build a dictionary in which the keys are the old priorities, while the values are the new ones.
Finally, we go through the tasks
dictionary and update the priorities.
You can use it "sorted" function, you don’t need to casting for set type;
from pprint import pp
tasks = [{'priority': 2, 'task': 'math', 'complete_time': 15},
{'priority': 10, 'task': 'french', 'complete_time': 90},
{'priority': 5, 'task': 'geography', 'complete_time': 45},
{'priority': 2, 'task': 'math', 'complete_time': 100}]
sorted_task = sorted(tasks, key=lambda val: val['priority'])
for order, task in enumerate(sorted_task):
task['priority'] = order
pp(sorted_task)
# output:
# [{'priority': 0, 'task': 'math', 'complete_time': 15},
# {'priority': 1, 'task': 'math', 'complete_time': 100},
# {'priority': 2, 'task': 'geography', 'complete_time': 45},
# {'priority': 3, 'task': 'french', 'complete_time': 90}]
If you want to sort by reverse, just add "reverse=True" parameter.