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 filter
s 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': []}