Get item location in python dictionary by value - python

I have a dictionary python with keys and values nested.
How do I find the object's index number by providing a value.
As for now, I can get values of the keys in specific object when I know the index of the object.
I mean, if I know the object's index number in the dictionary, I can get the key's and values in this specific object.
my_dict = {
"ftml": {
"people": {
"person": [
{
"#id": "Terach",
"#sex": "male",
"Death": {
"#year": ""
},
"Midrash": {
"#midrah": ""
},
"Old": {
"#age": ""
},
"Role": {
"#role": ""
},
"birth": {
"#year": ""
},
"father": {
"#id": "Nachor"
},
"mother": {
"#id": ""
},
"spouse": ""
},
{
"#id": "Avraham",
"#sex": "male",
"Death": {
"#year": "2123"
},
"Grandson": {
"#son1": "Esav",
"#son2": "Yaakov"
},
"Midrash": {
"#midrah": ""
},
"Old": {
"#age": "175"
},
"Role": {
"#role": ""
},
"birth": {
"#year": "1948"
},
"father": {
"#id": "Terach"
},
"mother": {
"#id": ""
},
"spouse": {
"#wife1": "Sara"
}
},
{
"#husband": "Avraham",
"#id": "Sara",
"#sex": "female"
},
{
"#id": "Nachor",
"#sex": "male",
"Death": {
"#year": ""
},
"Midrash": {
"#midrah": ""
},
"Old": {
"#age": ""
},
"Role": {
"#role": ""
},
"birth": {
"#year": ""
},
"father": {
"#id": "Terach"
},
"mother": {
"#id": ""
},
"spouse": ""
},
]
}
}
}
x = int(input("Type the chronological person number. (i.e 1 is Avraham): "))
print("First Name: ",my_dict['ftml']['people']['person'][x]["#id"]) #1 = avraham
I expect to ask the user for the #id and return the object's index number.
For example, if the user sends the program "Avraham" the program will return 1.
If the user is looking for Nachor the program will return 0.

I don't think revising the dict is a good idea.
Here is my solution:
First get the "position" of your list, i.e. what to find from.
list_to_find = my_dict['ftml']['people']['person']
The list_to_find is a list of dict (people), like
[{"#id": "Terach", '#sex': ...}, {"#id": 'Avraham', ...} ...]
Then what you want to do is to search in all the #id, so you can get all the #id by:
ids = [person['#id'] for person in list_to_find]
And then use index to get the index:
index = ids.index('Avraham')

In here I used dict comprehensions with enumerate() python Built-in Function. It's little bit confusing you. But you know the data structure about Dictionaries. For this example I didn't attach your my_dict dictionary cause it's too large.
>>> obj = {y["#id"]:x for x,y in list(enumerate(my_dict["ftml"]["people"]["person"]))}
>>> obj
{'Terach': 0, 'Avraham': 1, 'Sara': 2, 'Nachor': 3}
This output of the obj looks like the summary of the list of my_dict["ftml"]["people"]["person"]. Isn't it? For your question this obj is simply enough without extracting such a long dictionary and this is fast. If you confusing with dict comprehensions, hopefully this will understand for you.
>>> obj = {}
>>> for x,y in list(enumerate(my_dict["ftml"]["people"]["person"])):
... obj[y["#id"]] = x
...
>>> obj
{'Terach': 0, 'Avraham': 1, 'Sara': 2, 'Nachor': 3}
If you didn't understand what enumerate() does in here, check this small example which I directly get it from original documentation.
Return an enumerate object. iterable must be a sequence, an iterator, or some other object which supports iteration. The __next__() method of the iterator returned by enumerate() returns a tuple containing a count (from start which defaults to 0) and the values obtained from iterating over iterable.
>>> seasons = ['Spring', 'Summer', 'Fall', 'Winter']
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> list(enumerate(seasons, start=1))
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
According to above the example we are numbering seasons final output. I saw you comment in #Joery's answer. Now you want to insert a name and get an index of if it.
>>> x = input("Type the chronological person number. (i.e 1 is Avraham): ")
Type the chronological person id. (i.e 1 is Avraham): Avraham
>>> print(obj.get(x, None)) # if not match anything, will return None
1
So this 1 mean the 2nd element of my_dict["ftml"]["people"]["person"] list. Now you can easily access any of it. This is what get() function does.
Return the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError.
In you obj dictionary there are 4 keys available, Terach, Avraham, Sara and Nachor. When you enter one of these as your input, you'll get 0, 1, 2 or 3 as an output. According to the default value of get() function, it is None. When you enter value as an input which is not in obj dictionary mean you'll get the default value which is None.

just reverse the dictionary like so:
reversed_dict = {}
for i in range(0,len(my_dict['ftml']['people']['person'])):
reversed_dict[my_dict['ftml']['people']['person'][i]['#id']] = {'index':i}
print(reversed_dict)
print(reversed_dict['Avraham']['index'])
this should give you the outout of
{'Terach': {'index': 0}, 'Avraham': {'index': 1}, 'Sara': {'index': 2}, 'Nachor': {'index': 3}}
1

The most simple thing would probably be:
my_dict = {} # Defined in the question
x = int(input("Type the chronological person number. (i.e 1 is Avraham): "))
persons = my_dict['ftml']['people']['person']
for i, v in enumerate(persons):
if v['#id'] == x:
break
# i now has the most recent index
print(i)
Your intention: "For example, if the user sends the program "Avraham" the program will return 1. If the user is looking for Nachor the program will return 0." is implemented by this. However, above would work in in reverse... as the iteration will go from top to bottom in this representation...
reversed(persons)... :)

Related

How to get the values of dictionary python?

I have the below python dictionary stored as dictPython
{
"paging": {"count": 10, "start": 0, "links": []},
"elements": [
{
"organizationalTarget~": {
"vanityName": "vv",
"localizedName": "ViV",
"name": {
"localized": {"en_US": "ViV"},
"preferredLocale": {"country": "US", "language": "en"},
},
"primaryOrganizationType": "NONE",
"locations": [],
"id": 109,
},
"role": "ADMINISTRATOR",
},
],
}
I need to get the values of vanityName, localizedName and also the values from name->localized and name->preferredLocale.
I tried dictPython.keys() and it returned dict_keys(['paging', 'elements']).
Also I tried dictPython.values() and it returned me what is inside of the parenthesis({}).
I need to get [vv, ViV, ViV, US, en]
I am writing this in a form of answer, so I can get to explain it better without the comments characters limit
a dict in python is an efficient key/value structure or data type
for example dict_ = {'key1': 'val1', 'key2': 'val2'} to fetch key1 we can do it in 2 different ways
dict_.get(key1) this returns the value of the key in this case val1, this method has its advantage, that if the key1 is wrong or not found it returns None so no exceptions are raised. You can do dict_.get(key1, 'returning this string if the key is not found')
dict_['key1'] doing the same .get(...) but will raise a KeyError if the key is not found
So to answer your question after this introduction,
a dict can be thought of as nested dictionaries and/or objects inside of one another
to get your values you can do the following
# Fetch base dictionary to make code more readable
base_dict = dict_["elements"][0]["organizationalTarget~"]
# fetch name_dict following the same approach as above code
name_dict = base_dict["name"]
localized_dict = name_dict["localized"]
preferred_locale_dict = name_dict ["preferredLocale"]
so now we fetch all of the wanted data in their corresponding locations from your given dictionary, now to print the results, we can do the following
results_arr = []
for key1, key2 in zip(localized_dict, preferredLocale_dict):
results_arr.append(localized_dict.get(key1))
results_arr.append(preferred_locale_dict.get(key2))
print(results_arr)
What about:
dic = {
"paging": {"count": 10, "start": 0, "links": []},
"elements": [
{
"organizationalTarget~": {
"vanityName": "vv",
"localizedName": "ViV",
"name": {
"localized": {"en_US": "ViV"},
"preferredLocale": {"country": "US", "language": "en"},
},
"primaryOrganizationType": "NONE",
"locations": [],
"id": 109,
},
"role": "ADMINISTRATOR",
},
],
}
base = dic["elements"][0]["organizationalTarget~"]
c = base["name"]["localized"]
d = base["name"]["preferredLocale"]
output = [base["vanityName"], base["localizedName"]]
output.extend([c[key] for key in c])
output.extend([d[key] for key in d])
print(output)
outputs:
['vv', 'ViV', 'ViV', 'US', 'en']
So something like this?
[[x['organizationalTarget~']['vanityName'],
x['organizationalTarget~']['localizedName'],
x['organizationalTarget~']['name']['localized']['en_US'],
x['organizationalTarget~']['name']['preferredLocale']['country'],
x['organizationalTarget~']['name']['preferredLocale']['language'],
] for x in s['elements']]

How do we get dict value from object with changing variable

x = json.loads(y) #y is received from sender
print(x)
Output:
[
[
{
"O2JUKZ-4QUHH-6ZUZWF": {
"avg_price": "0.00000",
"cost": "0.00000",
"descr": {
"close": None,
"leverage": "0"
},
"status": "open",
"stoprice": "0.00000"
}
}
],
"openOrders",
{
"sequence": 1
}
]
Question: How do we assign order number (the characters in bold) to a variable, when It always changes?
Already tried: x[0][0]['O2JUKZ-4QUHH-6ZUZWF']['status'] to get the status (which works), but doesn't work anymore when "O2JUKZ-4QUHH-6ZUZWF" changes.
How do we assign order number to variable?
You could iterate over the dictionary with .items()
my_dictionary = data[0][0]
for order_code, sub_dict in my_dictionary.items():
# order_code is the dictionary key and order code you want
# sub_dict.get("status") will be the status

get data from a json

I want to get the data from a json. I have the idea of a loop to access all levels.
I have only been able to pull data from a single block.
print(output['body']['data'][0]['list'][0]['outUcastPkts'])
How do I get the other data?
import json,urllib.request
data = urllib.request.urlopen("http://172.0.0.0/statistic").read()
output = json.loads(data)
for elt in output['body']['data']:
print(output['body']['data'][0]['inUcastPktsAll'])
for elt in output['list']:
print(output['body']['data'][0]['list'][0]['outUcastPkts'])
{
"body": {
"data": [
{
"inUcastPktsAll": 3100617019,
"inMcastPktsAll": 7567,
"inBcastPktsAll": 8872,
"outPktsAll": 8585575441,
"outUcastPktsAll": 8220240108,
"outMcastPktsAll": 286184143,
"outBcastPktsAll": 79151190,
"list": [
{
"outUcastPkts": 117427359,
"outMcastPkts": 1990586,
"outBcastPkts": 246120
},
{
"outUcastPkts": 0,
"outMcastPkts": 0,
"outBcastPkts": 0
}
]
},
{
"inUcastPktsAll": 8269483865,
"inMcastPktsAll": 2405765,
"inBcastPktsAll": 124466,
"outPktsAll": 3101194852,
"outUcastPktsAll": 3101012296,
"outMcastPktsAll": 173409,
"outBcastPktsAll": 9147,
"list": [
{
"outUcastPkts": 3101012296,
"outMcastPkts": 90488,
"outBcastPkts": 9147
},
{
"outUcastPkts": 0,
"outMcastPkts": 0,
"outBcastPkts": 0
}
]
}
],
"msgs": [ "successful" ]
},
"header": {
"opCode": "1",
"token": "",
"state": "",
"version": 1
}
}
output = json.loads(data) #Type of output is a dictionary.
#Try to use ".get()" method.
print(output.get('body')) #Get values of key 'body'
print(output.get('body').get('data')) #Get a list of key 'data'
If a key doesn't exist, the '.get()' method will return None.
https://docs.python.org/3/library/stdtypes.html#dict.get
In python you can easily iterate over the objects of a list like so:
>>> l = [1, 2, 3, 7]
>>> for elem in l:
... print(elem)
...
1
2
3
7
This works regarding what can of object do you have in the list (integers, tuples, dictionaries). Having that in mind, your solution was not far off, you only to do the following changes:
for entry in output['body']['data']:
print(entry['inUcastPktsAll'])
for list_element in entry['list']:
print(list_element['outUcastPkts'])
This will give you the following for the json object you have provided:
3100617019
117427359
0
8269483865
3101012296
0

Why is the dictionary i created out of another dictionary using a for loop smaller?

bus_stops = jsoncalls.get_bus_stop()
print(len(bus_stops))
stop_map = {stop['Description']: stop for stop in bus_stops}
print('extracted dic: '+str(len(stop_map)))
here is what my code looks like. basically i create a dictionary out of another method i have from an api call. then i did what i think was to create another dictionary populated with only the values "description" from that dictionary.
the first print is the length of the first dictionary. the second print is the length of the second.
5024
extracted dic: 4457
the second dictionary is 600 items short! i am perplexed as to what could have caused this. can anyone advice me?
You're grouping the items by description by using it as a key. A key can only exist once. If two items have the same description, they'll occupy the same key, of which only the last one will survive.
Since dict keys are unique, I would bet you have repeated descriptions in your source dict. For example, suppose you have the following dataset:
bus_stops = [
{"Id": 1, "Description": "spam"},
{"Id": 2, "Description": "cheese"},
{"Id": 3, "Description": "spam"},
]
Note how only the last "spam" will be present in the result:
>>> stop_map = {stop['Description']: stop for stop in bus_stops}
{
'cheese': {'Description': 'cheese', 'Id': 2},
'spam': {'Description': 'spam', 'Id': 3}},
}
If this is the case and you want to group stops by description, you can use a dict with description as key and a list of stops as value - the setdefault method is handy for this kind of data transformation:
stop_map = {}
for stop in bus_stops:
stop_map.setdefault(stop["Description"], []).append(stop)
Result:
{
"cheese": [
{
"Id": 2,
"Description": "cheese"
},
],
"spam": [
{
"Id": 1,
"Description": "spam"
},
{
"Id": 3,
"Description": "spam"
},
],
}

Safe get when parent is null in dictionary

I am looking for a way to safe get a value from a nested dictionary.
.get() will give None if the value is not present in a dictionary but if a value is None None.get("value_2") will throw an error.
Sample Dictionary:
[
{
"value": {
"value_2": "string"
}
},
{
"value": null
}
]
When iterating through the array for 0th element let us say a a.get("value").get("value_2") will give string as output, but for the second element a.get("value").get("value_2") gives an error. There needs to be a check if value is None, if not only then get value_2
Is there any way to skip the if check and make python return None. If the dictionary is nested for more than one level then I will have to check for None at multiple levels.
I would suggest to implement function like below
vals = [
{
"value": {
"value_2": "string"
}
},
{
"value": None
}
]
def get_from_dict(dict_, path):
path = path.split("/")[::-1]
dict_ = dict_.get(path.pop())
while dict_ is not None and len(path)>0:
dict_ = dict_.get(path.pop())
return dict_
for a in vals:
print(get_from_dict(a, "value/value_2"))

Categories