I have the following structure in my json:
obj = {
'Name': 'David',
'Car': {
'Make': 'Ford',
'Year': 2008
}
}
I am given dot notation to refer to the object value, for example:
Car.Make ==> 'Form'
Given a string, such as "Car.Make", how would I programmatically fetch the attribute? In the above example, it would be:
obj.get('Car').get('Make')
But what about for a deeply-nested object, how would I extract the value given dot notation of "Attr1.Attr2.Attr3...Attrn" ?
obj = {
'Name': 'David',
'Car': {
'Make': 'Ford',
'Year': 2008
}
}
s = "Car.Make"
x = obj
keys = s.split(".")
for key in keys:
x = x[key]
print(x)
Result:
Ford
Or, in one-liner form:
from functools import reduce
print(reduce(lambda a,b: a[b], s.split("."), obj))
Here are some answers from Stackoverflow that propose a custom dictionary class that implements __getattr__ and __setattr__ to access the dictionary items:
How to use a dot "." to access members of dictionary?
Accessing dict keys like an attribute in Python?
Related
I have a dict myDict that look like this :
{
'score': 1,
'surname': 'AA AA',
'name': 'AAA AAA'
}
And I have an array of dict myArray that look like this :
[
{
'score': 0.9,
'surname': 'AA AA',
'name': 'AAA AAA'
},
{
'score': 0.6,
'surname': 'BB BB',
'name': 'BBB BBB'
},
...
]
I am looking for a function that will find in myArray, the element that have the same name and surname that myDict, and return the score.
Is there a way to achieve this without manualy itering over myArray ?
You can also just iterate through myArray with smth like this:
def find_score(myDict, myArray):
name, surname = myDict['name'], myDict['surname']
for i in myArray:
if i['name'] == name and i['surname'] == surname:
return i['score']
You can use a list comprehension, like this:
ls=[d for d in myArray if d["surname"]==myDict["surname"] and d["name"]==myDict["name"]]
This will give you a list of all dictionaries in myArray that match name and surname in myDict. If there will always only be one such value, you can retrieve the score with ls[0]["score"].
Not though, that while list comprehensions are neat and compact Pythonic ways to do things, technically you are still iterating over myArray.
Otherwise you could consider converting myArray to a Pandas DataFrame and using it's built-in filtering functions.
I have data in the form of a list of dicts, with some keys and values (the example below is for two keys/values, there could be more):
I would like to pythonically answer the question: what is john's age?
The simple solution I am using now is to iterate though the list and check for a matching value of name. Is there a more pythonic way to achieve the same?
data = [
{
'name': 'john',
'age': 10
},
{
'name': 'paul',
'age': 20
}
]
age = -1 # in case the name is not found
for d in data:
if d['name'] == 'john':
age = d['age']
print(age)
I would use next() and a generator expression.
The generator expression would be a one line equivalent to your for loop , and next() would get the next value from it (which when called first time is the first value).
Example -
next((d['age'] for d in data if d['name'].lower() == 'john'), -1)
The second argument to -1 is like the default value to return in case the generator expression does not have anymore values (in this case - it means if the name - john does not exist in the list) .
Demo -
>>> data = [
... {
... 'name': 'john',
... 'age': 10
... },
... {
... 'name': 'paul',
... 'age': 20
... }
... ]
>>>
>>> next((d['age'] for d in data if d['name'].lower() == 'john'), None)
10
You could create a dictionary with the name as key and age as value, then lookup the name:
age = {person['name']: person['age']
for person in data}['john']
Maybe what you want is a list of comprehension
age = [d['age'] for d in data if d['name'] == 'john'][0]
Also, you can use filter on the list this way :
age = filter(lambda u : u['name'] == 'john', data)[0]['age']
If you need to do this lookup for multiple names, it would be wise to generate a dict with name as a key -
new_dict = {datum['name']: data for datum in data}
new_dict['john']['age']
This way you can easily access it, and seems more pythonic. It might not be the performance optimum solution though, if your data set is too big to be a concern.
I have a list of details from an output for "set1" which are like "name", "place", "animal", "thing"
and a "set2" with the same details.
I want to create a dictionary with dict_names[setx]['name']... etc On these lines.
Is that the best way to do it? If not how do I do it?
I am not sure how 2D works in dictionary.. Any pointers?
It would have the following syntax
dict_names = {
'd1': {
'name': 'bob',
'place': 'lawn',
'animal': 'man'
},
'd2': {
'name': 'spot',
'place': 'bed',
'animal': 'dog'
}
}
You can then look things up like
>>> dict_names['d1']['name']
'bob'
To assign a new inner dict
dict_names['d1'] = {'name': 'bob', 'place': 'lawn', 'animal': 'man'}
To assign a specific value to an inner dict
dict_names['d1']['name'] = 'fred'
Something like this would work:
set1 = {
'name': 'Michael',
'place': 'London',
...
}
# same for set2
d = dict()
d['set1'] = set1
d['set2'] = set2
Then you can do:
d['set1']['name']
etc. It is better to think about it as a nested structure (instead of a 2D matrix):
{
'set1': {
'name': 'Michael',
'place': 'London',
...
}
'set2': {
'name': 'Michael',
'place': 'London',
...
}
}
Take a look here for an easy way to visualize nested dictionaries.
Something like this should work.
dictionary = dict()
dictionary[1] = dict()
dictionary[1][1] = 3
print(dictionary[1][1])
You can extend it to higher dimensions as well.
If I understand your question properly, what you need here is a nested dictionary.You can use the addict module to create nested dictionaries quite easily.
https://github.com/mewwts/addict
if the items in each set is ordered, you could use the below approach
body = Dict()
setx = ['person1','berlin','cat']
sety = ['person2','jena','dog']
setz = ['person3','leipzig','tiger']
for set_,s in zip([setx,sety,setz],['x','y','z']):
for item,item_identifier in zip(set_,['name','city','animmal']):
body[f'set{s}'][f'{item_identifier}'] = item
now you can easily access the items as follows.
print(body['setx']['name'])
Simple one-liner for a nested 2D dictionary ( dict_names = {} ) :
dict_names.setdefault('KeyX',{})['KeyY']='Value'
How can I sort a dictionary like this (simplified version):
x = {
'1': {
'type': 'a',
'created_at': 'date time object here',
},
'2': {
'type': 'b',
'created_at': 'date time object here',
},
'3': {
'type': 'a',
'created_at': 'date time object here',
},
}
I have a dictionary with structure like above with several hundred thousands keys, I need to sort it by created_at value, which is a date time object.
With a simple key function:
sorted(d.iteritems(), key=lambda i: i[1]['created_at'])
This produces a sorted list of (key, nested_dict) tuples, sorted on the 'created_at' key of the nested dictionaries.
In Python 3, replace iteritems() with items(). You cannot avoid creating a list; sorting requires an orderable, mutable sequence to move the items around in.
I have the following structure:
structure = {
'pizza': {
# other fields
'sorting': 2,
},
'burger': {
# other fields
'sorting': 3,
},
'baguette': {
# other fields
'sorting': 1,
}
}
From this structure I need the keys of the outer dictionary sorted by the sorting field of the inner dictionary, so the output is ['baguette', 'pizza', 'burger'].
Is there a simple enough way to do this?
The list.sort() method and the sorted() builtin function take a key argument, which is a function that's called for each item to be sorted, and the item is sorted based on the returnvalue of that keyfunction. So, write a function that takes a key in structure and returns the thing you want to sort on:
>>> def keyfunc(k):
... return structure[k]['sorting']
...
>>> sorted(structure, key=keyfunc)
['baguettes', 'pizza', 'burger']
You can use the sorted builtin function.
sorted(structure.keys(), key = lambda x: structure[x]['sorting'])