Sort Multidimensional Dict in Python - python

I'm trying to sort this dict based on the key "order". Kindly, find below sample dict :-
{'about-us': [{'name': 'CONSTITUTION', 'order': u'2', 'uri': 'constitution'},
{'name': 'EXECUTIVE COMMITTEE',
'order': u'3',
'uri': 'executive-committee'},
{'name': 'FINANCIAL INFO',
'order': u'4',
'uri': 'financial-info'},
{'name': 'SPONSORS AND AFFILIATIONS',
'order': u'5',
'uri': 'sponsors-and-affiliations'},
{'name': 'ABOUT', 'order': u'1', 'uri': 'about'}]}
Tried using this code, but I got an error
sorted(sub_links, key=lambda x: sub_links[x]['order'])
TypeError: list indices must be integers, not str
Any hint?

You can't sort the dictionary itself. Dictionary in python does not have an order.
Trying to sort dictionary will pass keys of the dictionary to the key function. sub_links[x] => sub_links['about-us']; sub_links[x]['order'] fails because sub_links[x] returns a list.
You can sort the list inside the dictionary: d['about-us']
Also the usage of the sorted function should be changed: sorted passes each item to the key function, not the index of the item.
>>> sorted(d['about-us'], key=lambda x: int(x['order']))
[{'uri': 'about', 'name': 'ABOUT', 'order': u'1'},
{'uri': 'constitution', 'name': 'CONSTITUTION', 'order': u'2'},
{'uri': 'executive-committee', 'name': 'EXECUTIVE COMMITTEE', 'order': u'3'},
{'uri': 'financial-info', 'name': 'FINANCIAL INFO', 'order': u'4'},
{'uri': 'sponsors-and-affiliations', 'name': 'SPONSORS AND AFFILIATIONS', 'order': u'5'}]
If you need to sort all the dictionary values in place, loop over the values.
for value in d.values(): # use `itervalues` In Python 2.x
value.sort(key=lambda x: int(x['order']))

falsetru showed what you probably meant to do, but here's an explanation of the error you are seeing:
The key lambda function receives the dictionary's keys as its argument x when called--in this case, the call looks something like this when performed on the one and only key in the dictionary:
# this is JUST for demonstrating the execution of the code--this is not actual Python code
lambda("about-us"):
return sub_links["about-us"]["order"]
When this executes, sub_links["about-us"] returns the value of that key, which is a list. When the next part of the statement executes (<the list that got returned>["order"]), the TypeError gets thrown because lists require integer indices.
There's a bigger problem here--it seems you called sorted on the whole dictionary, which only contains 1 value. It doesn't make sense to sort something with only 1 entry, and it should not be used to sort what you seem to want to sort, which is the inner list of dictionaries.
If you want to sort the inner list of dictionaries (the corresponding dict value for the "about-us" key), you'll need something like this (as falsetru also suggested):
sorted(sub_links["about-us"], key=lambda d: int(d["order"]))

Related

Sort list of dictionaries by key [duplicate]

This question already has answers here:
How do I sort a dictionary by key?
(32 answers)
Apply function to each element of a list
(4 answers)
Closed 5 months ago.
I have a list of dictionaries where the order of the keys is not consistent. Ideally I would like 'vid' to always come first with 'name' being second. As you can see below, sometimes 'name' comes first. How can I sort this list of dictionaries to always have 'vid' first?
viri_assets = [
{'vid': 'transpower_036', 'name': '221_02_PB_520_REF_174050'},
{'name': '242_07_DINA_HSTLR_YT_210238', 'vid': 'transpower_168'},
{'vid': 'transpower_170', 'name': '242_08_DINA_HSTLR_YT_210220'},
{'name': '251_PS04_PB_520_REF_109968', 'vid': 'transpower_166'},
{'vid': 'transpower_165', 'name': '251_PS05_PB_520_REF_109967'},
{'name': '31089', 'vid': 'transpower_064'}]
I have tried using sorted(viri_assets, key=lambda d: list(d.keys())) but it does not work.
You don't want to call sorted on your list, but on each dict of the list
Use .items() to get key-value pairs for each dict, and it'll sort them by the first element of the pair: the key. Set reverse to True to get "vid" before "name".
viri_assets = [{'vid': 'transpower_036', 'name': '221_02_PB_520_REF_174050'},
{'vid': 'transpower_065', 'name': '222_05_KAL_T2E_YT_344991'},
{'name': '226_02_INTL_PRSTR_ET_499802', 'vid': 'transpower_156'}]
viri_assets = [dict(sorted(d.items(), reverse=True)) for d in viri_assets]
print(viri_assets)
Output:
[{'vid': 'transpower_036', 'name': '221_02_PB_520_REF_174050'},
{'vid': 'transpower_065', 'name': '222_05_KAL_T2E_YT_344991'},
{'vid': 'transpower_156', 'name': '226_02_INTL_PRSTR_ET_499802'}]

Search lists inside dictionaries from API request

I'm trying to query a dictionary with a list and another dictionary inside. I'm using the deck of cards API and want to pull the value out.
drawCard='https://deckofcardsapi.com/api/deck/vx58tedq5moe/draw/?count=1'
response = requests.get(drawCard)
getValue = json.loads(response.text)
value= (getValue['cards'])
print (getValue)
print("")
print("")
print (value)
card= (getValue['cards'](''))
This is what I get when I print getValue.
{'deck_id': 'vx58tedq5moe', 'success': True, 'cards': [{'suit': 'SPADES', 'code': '0S', 'value': '10', 'images': {'png': 'https://deckofcardsapi.com/static/img/0S.png', 'svg': 'https://deckofcardsapi.com/static/img/0S.svg'}, 'image': 'https://deckofcardsapi.com/static/img/0S.png'}], 'remaining': 44}
I narrowed it down to this using getValue['cards'] but cant go any further.
[{'suit': 'SPADES', 'code': '0S', 'value': '10', 'images': {'png': 'https://deckofcardsapi.com/static/img/0S.png', 'svg': 'https://deckofcardsapi.com/static/img/0S.svg'}, 'image': 'https://deckofcardsapi.com/static/img/0S.png'}]
I want to grab the 10 from value
The value of getValue['cards'] is a list, so first you want to access the list element, getValue['cards'][0] then you can access the element 'value' with
getValue['cards'][0]['value']
If you want to get all value from all cards in the list of cards, you can use list comprehension to do something like
[c['value'] for c in getValue['cards']]
You go multiple levels down like this:
value= (getValue['cards']['value'])
BC 'cards' is the key to the list and 'value' is key to the value in the list witch have the value of 10.

How to get values from nested dict?

I'm new to robot and Python. I have a nested dictionary from where I need to get values but I can't access them.
${result} = Get Info from_here=location mode=aggregate
#{keys}= Get Dictionary Keys ${result}
${robot_dict}= Create Dictionary
:FOR ${key} IN #{keys}
\ Set To Dictionary ${robot_dict} ${key}=${result['${key}']}
Log Many ${robot_dict}
######Output from robot_dict is:
#{'Name1':
# {'nickname':
# {'Name': 'Name1', 'FirstName': 'Full', 'Boy':
# {'Age': 'N/A', 'Single': '0'},
# 'Girl':
# {'Height': '229057', 'Weight': 'N/A'}
# }
# },
#'Name2':{'nickname':
# {'Name': 'Name2', 'FirstName': 'Full', 'Boy':
# {'raw_pkt_count': '229059', 'Age': 'N/A'},
# 'Girl':
# {'Height': '0', 'Weight': 'N/A'}
# }
# }
#}
#############
Tried this:
${current_key} = Get Dictionary Keys ${robot_dict[Name1][nickname][Girl][Height]}
######Error: Resolving variable '${robot_dict[Name1][nickname][Girl][Height]}' failed: KeyError: 0
And this:
${current_key} = Get Dictionary Keys ${robot_dict} Name1.nickname.Girl.Height
#######Error: Dictionary does not contain key Name1.nickname.Girl.Height
When you use extended variable syntax, you have to treat the code as if it were python. Since the keys are strings, they need to be properly quoted. Here's the relevant part from the documentation:
The expression inside the curly brackets is evaluated as a Python expression, so that the base variable name is replaced with its value.
If the evaluation fails because of an invalid syntax or that the
queried attribute does not exist, an exception is raised and the test
fails.
${current_key} = Get Dictionary Keys ${robot_dict['Name1']['nickname']['Girl']['Height']}

Ordering a nested dictionary in python

I have a nested dictionary (category and subcategories), dict, that I am having trouble sorting.
The output of dict is:
{u'sports': {u'basketball': {'name': u'Basketball', 'slug': u'basketball'}, u'baseball': {'name': u'Baseball', 'slug': u'baseball'}}, u'dance': {u'salsa': {'name': u'Salsa', 'slug': u'salsa'}}, u'arts': {u'other-5': {'name': u'Other', 'slug': u'other-5'}, u'painting': {'name': u'Painting', 'slug': u'painting'}}, u'music': {u'cello': {'name': u'Cello', 'slug': u'cello'}, u'accordion': {'name': u'Accordion', 'slug': u'accordion'}}}
How can I sort this dictionary so that the 'other' subcategory always shows up at the end of the nested dictionary. For example the order for the "arts" category should be:
..., u'arts': {u'painting': {'name': u'Painting', 'slug': u'painting'}, u'other-5': {'name': u'Other', 'slug': u'other-5'}}...
You have some major concept misunderstanding about dictionary. Dictionary in python is like a hash table, hash table has no order. The output of the dict is really environment dependent so you couldn't depend on that. You might see one way of the output while other people see another way. You should consider using OrderedDict instead.
Python dictionaries (regular dict instances) are not sorted. If you want to sort your dict, you could:
from collections import OrderedDict
mynewdict = OrderedDict(sorted(yourdict.items()))
An OrderedDict does not provide a sorting mechanism, but only respect the order of the keys being inserted on it (we sort those keys calling sorted beforehand).
Since you need a specific criteria (lets say your keys are alphabetically ordered except for the "other" key which goes to the end), you need to declare it:
def mycustomsort(key):
return (0 if key != 'other' else 1, key)
mynewdict = OrderedDict(sorted(yourdict.items(), key=mycustomsort))
This way you are creating a tuple for the nested criteria: the first criteria is other vs. no-other, and so the 0 or 1 (since 1 is greater, other comes later), while the second criteria is the key itself. You can remove the second criteria and not return a tuple if you want, but only the 0 and 1, and the code will work without alphabetical sort.
This solution will not work if you plan to edit the dictionary later, and there is no standard class supporting that.

Multiple Assignments in Python dictionary comprehension

Lets say I have a list
demo = [['Adam', 'Chicago', 'Male', 'Bears'], ['Brandon', 'Miami', 'Male', 'Dolphins']]
I want to make a list of dictionaries using a comprehension that looks like
[{'Adam':'Chicago', 'Gender':'Male', 'Location':'Chicago', 'Team':'Bears'},
{'Brandon':'Miami', 'Gender':'Male', 'Location':'Miami', 'Team':'Dolphins'} }
It easy enough to assign two starting values to get something like
{ s[0]:s[1] for s in demo}
but is there a legitimate way to assign multiple values in this comprehension that may look like
{ s[0]:s[1],'Gender':s[2], 'Team':s[3] for s in demo}
Its such a specific question and the I dont know the terms for searching so Im having a hard time finding it and the above example is giving me a syntax error.
Dictionary comprehensions build single dictionaries, not lists of dictionaries. You say you want to make a list of dictionaries, so use a list comprehension to do that.
modified_demo = [{s[0]:s[1],'Gender':s[2], 'Team':s[3]} for s in demo]
You can use zip to turn each entry into a list of key-value pairs:
dicts= [dict(zip(('Name','Gender','Location', 'Team'), data) for data in demo]
You don't want a 'Name' label, you want to use the name as a label which duplicates location. So, now you need to fix up the dicts:
for d in dicts:
d[d['Name']] = d['Location']
del d['Name'] # or not, if you can tolerate the extra key
Alternatively, you can do this in one step:
dicts = [{name:location,'Location':location,'Gender':gender, 'Team':team} for name,location,gender,team in demo]
Your requirement just looks odd, are you sure you aren't trying to logically name the fields (which makes far more sense):
>>> demo = [['Adam', 'Chicago', 'Male', 'Bears'], ['Brandon', 'Miami', 'Male', 'Dolphins']]
>>> [dict(zip(['name', 'location', 'gender', 'team'], el)) for el in demo]
[{'gender': 'Male', 'team': 'Bears', 'name': 'Adam', 'location': 'Chicago'}, {'gender': 'Male', 'team': 'Dolphins', 'name': 'Brandon', 'location': 'Miami'}]

Categories

Resources