Home > OS >  Python Structured List Not Returning Values Using Reduce with Lambda
Python Structured List Not Returning Values Using Reduce with Lambda

Time:08-19

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 your nested_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
  • Related