Home > front end >  Combining multiple lambda expressions into one line
Combining multiple lambda expressions into one line

Time:12-31

implement in one line, using lambda expressions(map/filter/reduce), function that gets list of different types and returns a dictionary which has these keys: {‘c’: , ‘i’: , ‘f’: , ‘o’: }

'c' will present list of characters 'i' list of the integers 'f' list of the floats 'o' list of any other types

for exaple for the list: myList = ['a', 2, 3, 's', 2.23]

the output will be: {'c': ['a', 's'], 'i': [2, 3], 'f': [2.23], 'o': []}

So far is I made a method of it that works but I'll need somehow change it one line of code:

def q1a(myList):
   myDict = dict.fromkeys(('c', 'i', 'f', 'o'))
   myDict['c'] = list(filter(lambda x: type(x) is str, myList))
   myDict['i'] = list(filter(lambda x: type(x) is int, myList))
   myDict['f'] = list(filter(lambda x: type(x) is float, myList))
   myDict['o'] = list(filter(lambda x: type(x) is not float and type(x) is not int and type(x) is not str, myList))
   return myDict

CodePudding user response:

This gets around the need to assign to the keys one at a time:

def q1a(myList):
   return {
       'c': list(filter(lambda x: type(x) is str, myList)),
       'i': list(filter(lambda x: type(x) is int, myList)),
       'f': list(filter(lambda x: type(x) is float, myList)),
       'o': list(filter(lambda x: type(x) is not float and type(x) is not int and type(x) is not str, myList))
   }

CodePudding user response:

The assignment seems to be asking you to take a functional approach to this and create a single operation.

One option would be a single reduce that manipulates a dict. This isn't as natural in python as in other languages because most dict operations return None. But you can still do it in a functional way if you try (it's a one-liner broken up for a (minor) improvement in readability):

from functools import reduce

l = ['a', 2, 3, 's', 2.23]

res = reduce(
    lambda d, t: dict(d, **{t[1]: d[t[1]]   [t[0]]}),
    map(lambda el: (el, {str: 'c', int: 'i', float: 'f'}.get(type(el), 'o')) , l),
    dict.fromkeys('cifo', [])
)

print(res)
# {'c': ['a', 's'], 'i': [2, 3], 'f': [2.23], 'o': []}

This works by creating a list of tuples with the map():

list(map(lambda el: (el, {str: 'c', int: 'i', float: 'f'}.get(type(el), 'o')) , l),)
# [('a', 'c'), (2, 'i'), (3, 'i'), ('s', 'c'), (2.23, 'f')]

and then updating a dict inside the reduce that is initialized with empty lists created with dict.fromkeys('cifo', []).

CodePudding user response:

You could use list comprehensions and create a dictionary literal:

{
    'c': [e for e in myList if type(e) is str],
    'i': [e for e in myList if type(e) is int],
    'f': [e for e in myList if type(e) is float],
    'o': [e for e in myList if type(e) not in {float, int, str}]
}

CodePudding user response:

You can use the below ugly one-liner

out = dict(zip(['c','i','f','o'], map(list, (filter(lambda x:isinstance(x,str), lst), filter(lambda x:isinstance(x,int), lst), filter(lambda x:isinstance(x,float), lst), filter(lambda x: not isinstance(x,(str,float,int)), lst)))))

You can also use functools.reduce with a helper function (not exactly one liner but doesn't need multiple filters so saves time):

def add(d, x):
    d[x[0]].append(x[1])
    return d
from functools import reduce
out = reduce(add, 
             map(lambda x: (('c',x) if isinstance(x,str) 
                            else (('i',x) if isinstance(x,int) 
                                  else (('f',x) if isinstance(x,float) 
                                        else ('o',x)))), lst), 
             {'c':[],'i':[],'f':[],'o':[]})

Output:

{'c': ['a', 's'], 'i': [2, 3], 'f': [2.23], 'o': []}
  • Related