How can i traverse to particular key dynamically in python? - python-3.x

Probelm statement:
response= [{'HotelId': 8, 'IsFast': False, 'Payload': {'HotelInstaceId': 8, 'IsResetNeeded': False, 'HotelType': 'test', 'Product': {'Family': 'Times', 'Model': 'Roman', 'Type': 'Visible', 'Vendor': 'Royal'}, 'Hotel': {'DisplayBrightness': 80, 'LedColor': None, 'Location': '', 'Name': 'testing'}}}]
I want to verify the value of name "testing".
My code:
result = response["Data"][0]["Payload"]["Name"]
if result == "testing":
print("pass")
else:
print("fail")
New code:
tests = [{'a': 1},
{'b': {'a': 2}},
{'a': 3, 'b': {'a': 4}},
{'a': {'b': 5}},
{'a': {'a': 6}}]
def recursively_find_dict_values(self, d, tests, key="HotelType"):
output = []
for i, v in d.items():
if i == key:
output.append(v)
if isinstance(v, dict):
output.extend(self.recursively_find_dict_values(v, key, tests))
return output
for t in tests:
recursively_find_dict_values(t, key="HotelType")
i will get the response from another function and that response i will send to "recursively_find_dict_values" func as a argument..
Example inputs:
Input keys Output
"Name" "testing"
"DisplayBrightness" 80
"HotelType" "test"
but i want to do in generic way like if i pass "Name" or "DisplayBrightness" or any key to the function it should return the value and also if keys in nested dictionary then also it should return the value.
How can i achieve this?

I think this may be able to help you:
def recursively_find_dict_values(d, key):
output = []
for i,v in d.items():
if i == key:
output.append(v)
if isinstance(v, dict):
output.extend(recursively_find_dict_values(v, key))
return output
tests = [{'a': 1},
{'b': {'a': 2}},
{'a': 3, 'b': {'a': 4}},
{'a': {'b': 5}},
{'a': {'a': 6}}]
for t in tests:
print(recursively_find_dict_values(t, 'a'))
Try it online!
I would check all the examples to see if the functionality is to your liking. Note that if the value of 'a' is a dict, it will add a dict to the list, and if the dict value of 'a' also has a key 'a', both levels will be added to the dict (see the fifth example). Also, even if there is only one match, it will still return a list.
In this example, d is the name of your input dict:
# Getting all the values of key in d:
values = recursively_find_dict_values(d, key)
# Checking if key has value v in d:
if v in recursively_find_dict_values(d):
print('Success!')

Related

Python3 for loop over a dict

I am trying to get all the values individually for each asset (BCHUSD and TRXUSD).
What I want to do is something like this:
BCHUSD a = 301.340000 b = 301.160000 c = 301.280000
TRXUSD a = 0.0609450 b = 0.0609440 c = 0.0609540
Could someone tell me how I can do it please?
Regards!
import requests
import json
while True:
req = requests.get('https://api.kraken.com/0/public/Ticker?pair=BCHUSD,TRXUSD,XRPUSD')
print(req)
<Response [200]>
print(type(req))
<class 'requests.models.Response'>
obj = req.json()
print(type(obj))
<class 'dict'>
for k, v in obj.items():
if type(v) is dict and k:
for nk, nv in v.items():
print(nk, nv)
BCHUSD {'a': ['298.240000', '11', '11.000'], 'b': ['298.040000', '3', '3.000'], 'c':
['299.000000', '0.89507885'], 'v': ['38.42175237', '5614.56089299'], 'p':
['300.890848', '277.650439'], 't': [24, 2314], 'l': ['299.000000', '260.000000'], 'h':
['302.390000', '309.900000'], 'o': '299.000000'}
TRXUSD {'a': ['0.0608250', '4881', '4881.000'], 'b': ['0.0607820', '40500',
'40500.000'], 'c': ['0.0608630', '81.94337742'], 'v': ['21067.61432979',
'9622286.56922629'], 'p': ['0.0610566', '0.0589675'], 't': [25, 1729], 'l':
['0.0608630', '0.0562060'], 'h': ['0.0612840', '0.0618410'], 'o': '0.0611130'}
XXRPZUSD {'a': ['0.69018000', '666', '666.000'], 'b': ['0.69000000', '42829',
'42829.000'], 'c': ['0.69022000', '358.00000000'], 'v': ['287549.02071579',
'27810492.67564827'], 'p': ['0.69737332', '0.65981291'], 't': [429, 10340], 'l':
['0.69000000', '0.62229000'], 'h': ['0.70386000', '0.72105000'], 'o': '0.69935000'}
I think the following could help you as a starting point:
response_json = {
"title": "name",
"abc": {'a': [1,2,3], "b": [2,3,4]},
"ohter_stuff": "xxx",
"xyz": {'a': [10, 20 ,30], "b": [20, 30, 40]}
}
# select relevant key value pairs
data = {
key: value for key, value in response_json.items()
if isinstance(value, dict)
}
# get the inner subdict index length
length = len(data['abc']['a'])
# get the inner subdict keys
items = list(data['abc'].keys())
# loop and print
for index in range(length):
for name, subdict in data.items():
# join the items at index pairs into a string
index_items = " ".join(
f"{item} = {subdict[item][index]}"
for item in items
)
print(name, index_items)
This is a pure standard library python solution. If you can install other libraries, I would recommend to have a look into pandas.

Get only empty sub dictionary values from a dictionary of dictionaries

I have been going at this problem for some time now, it seems that no matter what solution I use, I get the wrong answer.
I have a dictionary such as
dict = {'a': {'name': 'Sam', 'likes': 'Cookies'},
'b': {'name': 'Margaret', 'likes': None},
'c': {'name': None, 'likes': None}}
What I need to get is
{'b': {'likes': None},
'c': {'name': None, 'likes': None}}
I have tried to use for comprehension to keep it as pythonic as possible
>>>{subd:{key:value for key,value in dict[subd].items() if not value} for subd in dict}
{'a': {},
'b': {'likes': None},
'c': {'name': None, 'likes': None}}
I understand that I am getting 'a' in the output since I am iterating through each sub dictionary and it does have all values in the parameters so the result is an empty {}, how can I ensure to skip subdictionaries if they dont have any empty values?
Some remarks:
Please refrain from using built in names, such as dict. These will usually lead to breaking code.
A dictionary comprehension, is only pythonic if the purpose remains clear. Using nested dictionary comprehensions, is usually not more readable than two separate lines.
In this case you only have two depth levels, so it would suffice to have two loops, where you only have to check if the final dictionary does not contain empty key values:
data = {'a': {'name': 'Sam', 'likes': 'Cookies'},
'b': {'name': 'Margaret', 'likes': None},
'c': {'name': None, 'likes': None}}
def get_none(dictionary):
result = {}
for key, value in dictionary.items():
result[key] = {k: v for k, v in value.items() if v is None}
return {k: v for k, v in result.items() if v}
if __name__ == '__main__':
print(get_none(data))
Resulting in:
{'b': {'likes': None}, 'c': {'name': None, 'likes': None}}
Edit
I changed the
dictionary = dictionary.copy()
line to a new dictionary called result. By doing this, I don't copy any large dictionary unnecessary.
you can this code:
dict = {'a':{'name': 'Sam', 'likes': 'Cookies'}, 'b':{'name': 'Margaret', 'likes': None}, 'c':{'name': None, 'likes': None}}
dic = {}
for elem in dict.keys():
dict_n = dict[elem]
di = {k: v for k, v in dict_n.items() if v is None}
res = {elem:di}
if di != {}:
dic.__setitem__(elem,di)
print(dic)
Output:
{'b': {'likes': None}, 'c': {'name': None, 'likes': None}}
setitem method to add a key-value pair to a dict
{k: nones
for k, d in dct.items()
if (nones := {k: v for k, v in d.items() if v is None})}

Python Groupby keys list of dictionaries

I have the following for instance:
x = [{'A':1},{'A':1},{'A':2},{'B':1},{'B':1},{'B':2},{'B':3},{'C':1},{'D':1}]
and I would like to get a dictionary like this:
x = [{'A': [1,2], 'B': [1,2,3], 'C':[1], 'D': [1]}]
Do you have any idea how I could get this please?
You could use a collections.defaultdict of sets to collect unique values, then convert the final result to a dictionary with values as lists using a dict comprehension:
from collections import defaultdict
lst = [{'A':1},{'A':1},{'A':2},{'B':1},{'B':1},{'B':2},{'B':3},{'C':1},{'D':1}]
result = defaultdict(set)
for dic in lst:
for key, value in dic.items():
result[key].add(value)
print({key: list(value) for key, value in result.items()})
Output:
{'A': [1, 2], 'B': [1, 2, 3], 'C': [1], 'D': [1]}
Although its probably better to add your data directly to the defaultdict to begin with, instead of creating a list of singleton dictionaries(don't recommend this data structure) then converting the result.
Using dict.setdefault
Ex:
x = [{'A':1},{'A':1},{'A':2},{'B':1},{'B':1},{'B':2},{'B':3},{'C':1},{'D':1}]
res = {}
for i in x:
for k, v in i.items():
res.setdefault(k, set()).add(v)
#or res = [{k: list(v) for k, v in res.items()}]
print(res)
Output:
{'A': {1, 2}, 'B': {1, 2, 3}, 'C': {1}, 'D': {1}}

The question given to me was to create a new dictionary with inverted key value pairs from the original dictionary

create a new dictionary(new_dict) with inverted key-value pairs from the original dictionary (my_dict)
def invert(dic_t):
new_dict={}
for key,value in dic_t.items():
new_dict[key]=value
new_dict[value]=key
return new_dict
my_dict = {
"A": "B",
"C": "D",
"E": "F"
}
print(invert(my_dict))
Output:
{'A': 'B', 'B': 'A', 'C': 'D', 'D': 'C', 'E': 'F', 'F': 'E'}
I am new to python so any help would be useful
What you are doing is correct, you just have to remove the line new_dict[key]=value as this represents the same old dictionary
def invert(dic_t):
new_dict={}
for key,value in dic_t.items():
# new_dict[key]=value
new_dict[value]=key
return new_dict
Also, you can use dictionary comprehension if you are looking for an one-line answer!
def invert(dict_t):
return {v:k for k, v in dict_t.items()}

generate items from dictionary

I'm using python 3.3
I have a dictionary
dict = {'a': (3,1), 'b': (1,2), 'c': (1,1)}
i'm trying to generate one item at a time
when I write item I mean
item1 = 'a': (3,1)
item2 = 'b': (1,2)
etc'
i have tried:
for key, value in dict.items():
temp = [key, value]
yield temp
or
for item in dict:
yield dict[item],item
but both don't generate what I want.
any help will be greatly appreciated
Thanks!
def my_generator(d):
for key, value in d.items():
yield {key: value}
d = {'a': (3,1), 'b': (1,2), 'c': (1,1)}
for subdict in my_generator(d):
print subdict
This would yield:
{'a': (3,1)}
{'b': (1,2)}
{'c': (1,1)}

Resources