Ruchi Naik
Ruchi Naik

Reputation: 21

Sort a list of key, values where value is dictionary AND sorting needs to be done on STRING value in the dictionary

Here is my list in python:

team_map = [('31983', {'team_sdsk_list': [], 'team_name': 'Commercials', 'in_progress': 0, 'completed': 0, 'not_started': 0}),
 ('32935', {'team_sdsk_list': [], 'team_name': 'DL Platform', 'in_progress': 0, 'completed': 0, 'not_started': 0}),
 ('32955', {'team_sdsk_list': [{'sdsk_summary': 'Task - BSDM Product Readiness (MiFIR Transparency Data package)', 'parent_target_launch_date': '2017-08-21', 'parent_sdsk_number': 774079489, 'attributes': [{'status': 'Complete', 'label': 'DL CONTENT<BR>UPDATED'}], 'rep': 'abc', 'parent_sdsk_product_mgr': 'xyz', 'sdsk_number': 1234, 'parent_sdsk_summary': 'Data Package'}], 'team_name': 'BSDM', 'in_progress': 0, 'completed': 1, 'not_started': 0})]

I need to sort this list so that the output is ordered alphabetically based on team_name. notice that team_name is a part of the dictionary, which is the 'value' of the list. so the output should be this:

[('32955', {'team_sdsk_list': [{'sdsk_summary': 'Task - BSDM Product Readiness (MiFIR Transparency Data package)', 'parent_target_launch_date': '2017-08-21', 'parent_sdsk_number': 774079489, 'attributes': [{'status': 'Complete', 'label': 'DL CONTENT<BR>UPDATED'}], 'rep': 'abc', 'parent_sdsk_product_mgr': 'xyz', 'sdsk_number': 1234, 'parent_sdsk_summary': 'Data Package'}], 'team_name': 'BSDM', 'in_progress': 0, 'completed': 1, 'not_started': 0}),
('31983', {'team_sdsk_list': [], 'team_name': 'Commercials', 'in_progress': 0, 'completed': 0, 'not_started': 0}),
('32935', {'team_sdsk_list': [], 'team_name': 'DL Platform', 'in_progress': 0, 'completed': 0, 'not_started': 0})]

I tried this:

sorted_team_map = sorted(team_map.items(), key=operator.itemgetter('team_name'))

but that gives me an error.
Please help me with the sort function.

Upvotes: 1

Views: 55

Answers (3)

Jean-Fran&#231;ois Fabre
Jean-Fran&#231;ois Fabre

Reputation: 140168

your input data is not a dictionary but a list of tuples. Each tuple second element is the dictionary you want to use to sort with a given value.

sorted_team_map = sorted(team_map, key=lambda x : x[1]['team_name'])

no .items() and take the second item of the tuple before accessing the key

How to fix such errors in the future ? (How did I fix your code ?):

  • your first attempt triggers a AttributeError: 'list' object has no attribute 'items' error. Which one calls items() ?: team_map. So team_map is a list after all, no need for a function to iterate on a list
  • once fixed, you get a second error: TypeError: tuple indices must be integers, not str. That's because itemgetter passed your key to something that isn't a dictionary but a tuple. You need to go one level deeper to reach your dictionary.

Upvotes: 3

Joe Iddon
Joe Iddon

Reputation: 20414

So you want to sort the team_map list based on the "team_name" attribute of the dictionary which is the second element in each tuple.

To get this, we take t (the tuple) and take the second element with t[1] (the dictionary) and sort based on the ["team_name"] attribute:

sorted(team_map, key=lambda t: t[1]["team_name"])

which gives the expected output:

[('32955', {'team_name': 'BSDM', 'team_sdsk_list': [{'parent_target_launch_date': '2017-08-21', 'parent_sdsk_number': 774079489, 'parent_sdsk_product_mgr': 'xyz', 'parent_sdsk_summary': 'Data Package', 'sdsk_summary': 'Task - BSDM Product Readiness (MiFIR Transparency Data package)', 'attributes': [{'label': 'DL CONTENT<BR>UPDATED', 'status': 'Complete'}], 'sdsk_number': 1234, 'rep': 'abc'}], 'completed': 1, 'in_progress': 0, 'not_started': 0}), ('31983', {'team_name': 'Commercials', 'team_sdsk_list': [], 'completed': 0, 'in_progress': 0, 'not_started': 0}), ('32935', {'team_name': 'DL Platform', 'team_sdsk_list': [], 'completed': 0, 'in_progress': 0, 'not_started': 0})]

Note that rather than using the built-in sorted() function and assigning the result of this back to team_map (which is what I assume you will do). You can also sort the list in place with team_map.sort.

So you could achieve the same result as above with:

team_map.sort(key=lambda t: t[1]["team_name"])

Upvotes: 2

Ajax1234
Ajax1234

Reputation: 71451

You need to access the dictionary stored at the last position in each tuple in the sorted key and utilize the value stored for "team_name":

team_map = [('31983', {'team_sdsk_list': [], 'team_name':'Commercials', 'in_progress': 0, 'completed': 0, 'not_started': 0}),
  ('32935', {'team_sdsk_list': [], 'team_name': 'DL Platform', 'in_progress': 0, 'completed': 0, 'not_started': 0}),
  ('32955', {'team_sdsk_list': [{'sdsk_summary': 'Task - BSDM Product Readiness (MiFIR Transparency Data package)', 'parent_target_launch_date': '2017-08-21', 'parent_sdsk_number': 774079489, 'attributes': [{'status': 'Complete', 'label': 'DL CONTENT<BR>UPDATED'}], 'rep': 'abc', 'parent_sdsk_product_mgr': 'xyz', 'sdsk_number': 1234, 'parent_sdsk_summary': 'Data Package'}], 'team_name': 'BSDM', 'in_progress': 0, 'completed': 1, 'not_started': 0})]
final_team = sorted(team_map, key=lambda x:x[-1]['team_name'])

Output:

[('32955', {'team_sdsk_list': [{'sdsk_summary': 'Task - BSDM Product Readiness (MiFIR Transparency Data package)', 'parent_target_launch_date': '2017-08-21', 'sdsk_number': 1234, 'attributes': [{'status': 'Complete', 'label': 'DL CONTENT<BR>UPDATED'}], 'parent_sdsk_number': 774079489, 'parent_sdsk_product_mgr': 'xyz', 'rep': 'abc', 'parent_sdsk_summary': 'Data Package'}], 'completed': 1, 'in_progress': 0, 'team_name': 'BSDM', 'not_started': 0}), ('31983', {'team_sdsk_list': [], 'completed': 0, 'in_progress': 0, 'team_name': 'Commercials', 'not_started': 0}), ('32935', {'team_sdsk_list': [], 'completed': 0, 'in_progress': 0, 'team_name': 'DL Platform', 'not_started': 0})]

Upvotes: 2

Related Questions