Home > Net >  What is the correct way to write this function?
What is the correct way to write this function?

Time:11-02

I was making a program where first parameter is a list and second parameter is a list of dictionaries. I want to return a list of lists like this:

As an example, if this were a function call:

make_lists(['Example'], 
           [{'Example': 'Made-up', 'Extra Keys' : 'Possible'}]
)

the expected return value would be:

[ ['Made-up'] ]

As an second example, if this were a function call:

make_lists(['Hint', 'Num'],
           [{'Hint': 'Length 2 Not Required', 'Num' : 8675309},
            {'Num': 1, 'Hint' : 'Use 1st param order'}]
)

the expected return value would be:

[ ['Length 2 Not Required', 8675309],    
  ['Use 1st param order', 1] 
]

I have written a code for this but my code does not return a list of lists, it just returns a single list. Please can someone explain?

def make_lists(s,lod):
  a = []
  lol =[]
  i = 0
  for x in lod:
      for y in x:
        for k in s:
          if(y==k):
            lol.append(x.get(y))
            i = i 1
  return lol

Expected Output:

[ ['Length 2 Not Required', 8675309],['Use 1st param order', 1] ]

Output:

['Length 2 Not Required', 8675309, 1, 'Use 1st param order']

CodePudding user response:

The whole point of dictionaries, is that you can access them by key:

def make_lists(keys, dicts):
   result = []
   for d in dicts:
      vals = [d[k] for k in keys if k in d]
      if len(vals) > 0:
          result.append(vals)
   return result

Let's have a look what happens here:

We still have the result array, which accumulates the answers, but now it's called result instead of lol

Next we iterate through every dictionary:

for d in dicts:

For each dictionary d, we create a list, which is a lookup in that dictionary for the keys in keys, if the key k is in the dictionary d:

vals = [d[k] for k in keys if k in d]

The specs don't detail this, but I assume if none of the keys are in the dictionary, you don't want it added to the array. For that, we have a check if vals have any results, and only then we add it to the results:

if len(vals) > 0:
    result.append(vals)

CodePudding user response:

Try this code - I've managed to modify your existing code slighty, and added explanation in the comments. Essentially, you just need to use a sub-list and add that to the master list lol, and then in each loop iteration over elements in lod, append to the sub-list instead of the outermost list.

def make_lists(s,lod):
  a = []
  lol =[]
  i = 0
  for x in lod:
      ## Added
      # Here we want to create a new list, and add it as a sub-list
      # within 'lol'
      lols = []
      lol.append(lols)
      ## Done
      for y in x:
        for k in s:
          if(y==k):
            # Changed 'lol' to 'lols' here
            lols.append(x.get(y))
            i = i 1
  return lol


print(make_lists(['Example'], [{'Example': 'Made-up', 'Extra Keys' : 'Possible'}]))
print(make_lists(['Hint', 'Num'], [{'Hint': 'Length 2 Not Required', 'Num' : 8675309}, {'Num': 1, 'Hint' : 'Use 1st param order'}]))

Prints:

[['Made-up']]
[['Length 2 Not Required', 8675309], [1, 'Use 1st param order']]

A simpler solution

For a cleaner (and potentially more efficient approach), I'd suggest using builtins like map and using a list comprehension to tackle this problem:

def make_lists(s, lod):
    return [[*map(dict_obj.get, s)] for dict_obj in lod]

But note, that this approach includes elements as None in cases where the desired keys in s are not present in the dictionary objects within the list lod.

To work around that, you can pass the result of map to the filter builtin function so that None values (which represent missing keys in dictionaries) are then stripped out in the result:

def make_lists(s, lod):
    return [[*filter(None, map(dict_obj.get, s))] for dict_obj in lod]


print(make_lists(['Example'], [{'Extra Keys' : 'Possible'}]))
print(make_lists(['Hint', 'Num'], [{'Num' : 8675309}, {'Num': 1, 'Hint' : 'Use 1st param order'}]))

Output:

[[]]
[[8675309], ['Use 1st param order', 1]]
  • Related