I have inherited Python code which I don't fully understand yet. Here is a structured list which needs only values from the Alternatives
key to be returned by a function. The data is like:
{
'Response':
[
{
'SavingsMessage': '',
'SavingNotification':
[
{'AuthorizationNumber': '12345' 'Alternatives': []},
{'AuthorizationNumber': '6666', 'Alternatives': [{'NDC': '99999'} ]
]
}
Above data is in a nested_value
variable and is passed to a function in such format:
level_two = get_nested_value_IRFAN([nested_value,*schema[key][level_one_key][level_one_key]])
while the values of the *schema[key][level_one_key][level_one_key]]
is:
[0, 'Response', 0, 'SavingNotification', 0, 'Alternatives']
And here is the function itself:
def get_nested_value_IRFAN(path):
return functools.reduce(lambda a,b:a[b],path)
The function should return only the values of the Alternatives key, per my understanding of the code but nothing is returned by the function--just blank []
returns? Or I could use nested_value
variable in a different way to extract the values of the Alternative
key. I have tried a few things but nothing has worked so far.
Thanks in advance!
CodePudding user response:
The approach using reduce
is fine, but there are a few problems with your code and/or data:
- first, your
nested_value
is not structured properly; there are a few closing parens and a comma missing (and possibly and entire outer layer) - instead of chaining the actual data to the path, you can use the third parameter of
reduce
:initializer
- the first key in your path is
0
, but in yournested_value
, the outermost structure is a dictionary
Or should there be another list around that? If there is another list, then []
would actually be the correct response for the given path and data. In any case, I would suggest at least using the initializer
parameter to make the code a lot clearer:
nested_value = [{'Response': [{'SavingsMessage': '',
'SavingNotification': [{'AuthorizationNumber': '12345',
'Alternatives': []},
{'AuthorizationNumber': '6666', 'Alternatives': [{'NDC': '99999'}]}]}]}]
def get_nested_value_IRFAN(path, data):
return functools.reduce(lambda a, b: a[b], path, data)
# using 1 instead of 0 as last list index for clearer output
path = [0, 'Response', 0, 'SavingNotification', 1, 'Alternatives']
val = get_nested_value_IRFAN(path, nested_value)
# [{'NDC': '99999'}], or [] for original path
CodePudding user response:
Because comments are limited in space and formatting, I'm posting an answer.
What you've given us:
nested_value = {
'Response':
[
{
'SavingsMessage': '',
'SavingNotification':
[
{'AuthorizationNumber': '12345' 'Alternatives': []},
{'AuthorizationNumber': '6666', 'Alternatives': [{'NDC': '99999'} ]
]
}
path = [0, 'Response', 0, 'SavingNotification', 0, 'Alternatives']
def get_nested_value_IRFAN(path):
return functools.reduce(lambda a,b:a[b],path)
get_nested_value_IRFAN([nest_value, path])
functools.reduce()
takes a function and a dataset to iterate over. The passed in function stores the result of the previous iteration in a
and gets the new value to use in b
. On the first iteration it takes in the first 2 elements of the list (path
in our case).
So the iterations, while applying the function, look like:
a = the nested_value data structure wrapped in [], b = 0
a = the nested_value data structed, b = "Response"
a = nested_value["Response"], b = 0
a = nested_value["Response"][0], b = "SavingNotification"
a = nested_value["Response"][0]["SavingNotification"], b = 0
# below is the last iteration
a = nested_value["Response"][0]["SavingNotification"][0], b = "Alternatives"
# which returns nested_value["Response"][0]["SavingNotification"][0]["Alternatives"]
# which is also []
You can create a loop to get the other values with minimal effort like so:
dkey = schema[key][level_one_key][level_one_key]
level_two = get_nested_value_IRFAN([nested_value,*dkey[:-2]])
for e in level_two:
# Okay... so this one should work... but if it doesn't, then you can do...
print(e[dkey[-1]])
print(e["Alternatives"]
# do what you want with e