It hasn't been long since I started learning python, but I really want to dig in it. And dig it hard. So here is a task I've been studying for a while but haven't cracked yet:
I am given a mixed combination of nested dictionaries and lists (let's call it "combination"), and I need to implement function that will allow accessing nested elements as object attributes, also somehow treating combination elements as iterable. This should look something like this:
combination = {
'item1': 3.14,
'item2': 42,
'items': [
'text text text',
{
'field1': 'a',
'field2': 'b',
},
{
'field1': 'c',
'field2': 'd',
},
]
}
def function(combination):
...
so thatlist(function(combination).items.field1)
will give: ['a', 'c']
, andlist(function(combination).item1)
will give: [3.14]
.
Edit As mentioned by @FM, I missed description of handling non-dict elements:
list(function(combination).items[0])
>>> ['text text text']
I tried implementing a class (kudos to Marc) to help me:
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
and then using it in the function like return Struct(**combination)
While being very nifty, it is only the first step to the desired result.
But as the next step needs to go deeper, it overwhelms me and I can't make it on myself.
Therefore, I kindly ask for your help.
Michael.
Method 1 : Using the json module. We can solve this particular problem by importing the json module and use a custom object hook in the json. loads() method.
Basically the same way you would flatten a nested list, you just have to do the extra work for iterating the dict by key/value, creating new keys for your new dictionary and creating the dictionary at final step. For Python >= 3.3, change the import to from collections.
Adding or updating nested dictionary items is easy. Just refer to the item by its key and assign a value. If the key is already present in the dictionary, its value is replaced by the new one. If the key is new, it is added to the dictionary with its value.
In Python, we use “ del “ statement to delete elements from nested dictionary.
How about:
class ComboParser(object):
def __init__(self,data):
self.data=data
def __getattr__(self,key):
try:
return ComboParser(self.data[key])
except TypeError:
result=[]
for item in self.data:
if key in item:
try:
result.append(item[key])
except TypeError: pass
return ComboParser(result)
def __getitem__(self,key):
return ComboParser(self.data[key])
def __iter__(self):
if isinstance(self.data,basestring):
# self.data might be a str or unicode object
yield self.data
else:
# self.data might be a list or tuple
try:
for item in self.data:
yield item
except TypeError:
# self.data might be an int or float
yield self.data
def __length_hint__(self):
return len(self.data)
which yields:
combination = {
'item1': 3.14,
'item2': 42,
'items': [
'text text text',
{
'field1': 'a',
'field2': 'b',
},
{
'field1': 'c',
'field2': 'd',
},
{
'field1': 'e',
'field3': 'f',
},
]
}
print(list(ComboParser(combination).item1))
# [3.1400000000000001]
print(list(ComboParser(combination).items))
# ['text text text', {'field2': 'b', 'field1': 'a'}, {'field2': 'd', 'field1': 'c'}, {'field3': 'f', 'field1': 'e'}]
print(list(ComboParser(combination).items[0]))
# ['text text text']
print(list(ComboParser(combination).items.field1))
# ['a', 'c', 'e']
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With