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!

Asked By: user3406207

||

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 sets, which are un-ordered (contrary to the lists), 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.

Answered By: GregoirePelegrin

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.

Answered By: Sezer BOZKIR
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.