Handle dicts/json with nested elements - python

tldr; Python 3.8. I want to work with a ‘clean’ dict with no empty entries to generate an adequate json output. For this case I need a function which handles it and supported a nested structure. This solution should be generic enough to work with n nested objects.
I want to work with a ‘clean’ dict with no empty entries to generate an adequate json output in Python 3.8. Internally I use a dict to store everything which will later dump to the disk. I know that {} is a valid json (and {“data”:{}} also) but IMHO it’s not clean. Parsing this kind of json only shows that nothing useful is stored.
So the idea is to avoid this unclean json by checking key/values which are added or removed to the json. This should support nested values to, like {"os":{"network":{"ip":"”localhost”"}}} (any depth), usable in an OOP style, e.g. def handleElement(key,value,**sections). If the value is empty, it should ‘clean up’ the dict removing every section if the section has no content.
After hours of searching I found neither a python build-in way to do this or some extensions or solutions on the web. I tried a lot by myself, but I found no way to iterate smooth over the dict and work on it. Because the calling syntax for dicts with nested elements is dict[][][]… I found no way to iterate over the dict and call the nested elements without coding every depth by hand.
Do you have any good idea? If you need more information or something is unclear, please ask!
Examples:
dict before: {}
call handleElement(“ip”,”localhost”, [os, network])
dic after: {“os”: {“network”: {“ip”: “localhost”}}
call handleElement (“ip”,””, [os, network])
dic after: {}
call handleElement (“ip”,”localhost”, [os, network])
call handleElement (“subnetmask”,”full”, [os, network])
dic after: {“os”: {“network”: {“ip”: “localhost”, “subnetmask”:”full”}}
call handleElement (“ip”,””, [os, network])
dic after: {“os”: {“network”: { “subnetmask”:”full”}}

You may not need a recursive approache, what you need is
when the value is not empty
build the path of the parents
set the key/value mapping
def handle_element(item, key, value, parent_list):
if value: # 1.
for parent in parent_list:
item.setdefault(parent, {}) # 2. add the parent with empty dict
item = item[parent] # go further in the dict
item[key] = value # 3.
CODE DEMO

Related

Redis HGETALL returns each key-value as byte objects individually

I am using Python as client to interact with redis and using the following Python library to do so:
https://github.com/redis/redis-py
When I run the command:
redis_return = conn.hgetall('my-hash-key')
What I get in return is a dictionary with all its elements as bytes objects individually, like:
{b'key1': b'value1', b'key2': b'value2'}
Since I need them as string I am looping over the dictionary and on each iteration decoding they key and value, something like:
mydict = dict()
for keys in redis_return:
mydict[keys.decode('utf-8')] = redis_return[keys].decode('utf-8')
I am getting the results in mydict as I need it, but is this the right approach?
Seems tedious and I wonder if there is a better way?

how to access values in a dictionary in python without knowing the actual values?

I am a python rookie and so my question is simple (yet I couldn't find the answer here):
I need to access values in my dictionary (named 'database') but without knowing the actual values. So lets say I want to print the first value of the dictionary whatever it is. I found this:
print(database.values()[0].keys()[0])
Which seems to be what I'm looking for but when running the script I get this error:
TypeError: 'database' object does not support indexing
Can you please help?
You might want to check out Ordered Dict:
As others mentioned in the comments, you would get the elements in no particular order because dictionaries are unordered.
This sample code works:
from collections import OrderedDict
database = OrderedDict()
database = {
"key1": {"key10": "value10", "key11": "value11"},
"key2": {"key20": "value20", "key21": "value21"}
}
If you want to print out or access all first dictionary keys in database.values() list, you may use something like this:
for key, value in database.items():
print value.keys()[0]
If you want to just access first key of the first item in database.values(), this may be useful:
print database.values()[0].keys()[0]
Hope this helps.

Parsing JSON in Python (Reverse dictionary search)

I'm using Python and "requests" to practice the use of API. I've had success with basic requests and parsing, but having difficulty with list comprehension for a more complex project.
I requested from a server and got a dictionary. From there, I used:
participant_search = (match1_request['participantIdentities'])
To convert the values of the participantIdentities key to get the following data:
[{'player':
{'summonerName': 'Crescent Bladex',
'matchHistoryUri': '/v1/stats/player_history/NA1/226413119',
'summonerId': 63523774,
'profileIcon': 870},
'participantId': 1},
My goal here is to combine the summonerId and participantId to one list. Which is easy normally, but the order of ParticipantIdentities is randomized. So the player I want information on will sometimes be 1st on the list, and other times third.
So I can't use the var = list[0] like how I would normally do.
I have access to summonerId, so I'm thinking I can search the list the summonerId, then somehow collect all the information around it. For instance, if I knew 63523774 then I could find the key for it. From here, is it possible to find the parent list of the key?
Any guidance would be appreciated.
Edit (Clarification):
Here's the data I'm working with: http://pastebin.com/spHk8VP0
At line 1691 is where participant the nested dictionary 'participantIdentities' is. From here, there are 10 dictionaries. These 10 dictionaries include two nested dictionaries, "player" and "participantId".
My goal is to search these 10 dictionaries for the one dictionary that has the summonerId. The summonerId is something I already know before I make this request to the server.
So I'm looking for some sort of "search" method, that goes beyond "true/false". A search method that, if a value is found within an object, the entire dictionary (key:value) is given.
Not sure if I properly understood you, but would this work?
for i in range(len(match1_request['participantIdentities'])):
if(match1_request['participantIdentities'][i]['summonerid'] == '63523774':
# do whatever you want with it.
i becomes the index you're searching for.
ds = match1_request['participantIdentities']
result_ = [d for d in ds if d["player"]["summonerId"] == 12345]
result = result_[0] if result_ else {}
See if it works for you.
You can use a dict comprehension to build a dict wich uses summonerIds as keys:
players_list = response['participantIdentities']
{p['player']['summonerId']: p['participantId'] for p in players_list}
I think what you are asking for is: "How do I get the stats for a given a summoner?"
You'll need a mapping of participantId to summonerId.
For example, would it be helpful to know this?
summoner[1] = 63523774
summoner[2] = 44610089
...
If so, then:
# This is probably what you are asking for:
summoner = {ident['participantId']: ident['player']['summonerId']
for ident in match1_request['participantIdentities']}
# Then you can do this:
summoner_stats = {summoner[p['participantId']]: p['stats']
for p in match1_request['participants']}
# And to lookup a particular summoner's stats:
print summoner_stats[44610089]
(ref: raw data you pasted)

python nested list and dicts, trouble accesing and setting

I am originally a c guy but recently I started doing some stuff in python.
The things that gives me trouble is the more advanced data structures in python.
I could do it all with multiple list like in c but that would just be boring right?
anyway here I have a data structure which is basically a list of dicts where the value field of the dict is another list of 2 key-value pairs:
clients = [
{'client1':[{'test':'testvalue','status':'statusvalue'}]},
{'client2':[{'test':'testvalue','status':'statusvalue'}]},
{'client3':[{'test':'testvalue','status':'statusvalue'}]}
]
now I want to be able to acces the testvalue and statusvalue fields and modify or read them. based on the position in the list.
in pseudocode it would be something like:
for i in range(0,clients):
getvalue(clients[i].'test')
setvalue(clients[i].'test')
getvalue(clients[i].'status')
setvalue(clients[i].'status')
in the end I want to use this data structure to render a html page with jinja2
For a start, in Python you should (almost) never iterate over range(len(something)). You iterate over something.
Secondly, your data structure is wrong. There's no point having a list of dicts, each dict containing a single key/value pair and each value consisting of a list with a single item. You should just have a dict of dicts: you can still iterate over it.
clients = {
'client1':{'test':'testvalue','status':'statusvalue'},
'client2':{'test':'testvalue','status':'statusvalue'},
'client3':{'test':'testvalue','status':'statusvalue'},
}
for key, value in clients.iteritems():
print value['test']
value['test'] = 'newvalue'
I have noticed that you put a dictionary inside a list as the value for each client.
I think you may wish to re-configure your data structure as such:
clients = [
{'client1':{'test':'testvalue','status':'statusvalue'}}
{'client2':{'test':'testvalue','status':'statusvalue'}}
{'client3':{'test':'testvalue','status':'statusvalue'}}
]
Therefore, you can begin iterating as such:
for client in clients:
for k, v in client.iteritems(): #this unpacks client into 'client' (k) and {'val'...} (v)
print v['test'] #this gets the value of test.
v['test'] = 'some_new_value' #this sets the value of test.

ConfigParser Get Key on given Value

Using ConfigParser I can read value of key easily as shown in the example below-
#config.cfg
[NODE]
192.168.31.22 = node22
192.168.31.23 = node23
192.168.31.26 = node26
#PYTHON CODE
config = ConfigParser.RawConfigParser()
config.readfp(open("config.cfg"))
print config.get("NODE", "192.168.31.22")
>>>node22
Sometime it is required that I read "key" based on given value.
Is there any built-in function to get KEY based on the given VALUE or any workaround for this ?
print config.FUNCTIONXYZ("NODE", "node22")
>>>192.168.31.22
Thank you.
No, there is no direct way. Internally, ConfigParser reads the configuration file into a nested dictionary, and in each sections keys are mapped to values, not the other way around. Frankly, I'm not sure why you want this, but I suspect it's not a common request :)
Implementing your own is very easy, however:
# items in section 'NODE': key, value pairs
for key, value in config.items('NODE'):
if value == WHAT_I_NEED:
print key
If you need many such lookups on a large configuration, consider placing items into a dict first.

Categories