Home > Mobile >  call a method in map and lambda using dictionary as input in python
call a method in map and lambda using dictionary as input in python

Time:12-24

test_input = {"oneone": 1, "twotwo": 2, "threethree": 3}

def testmethod(no):
    print(f"Number {no}")
    return True, f"Number {no}"

Without using lambda and map:

d = {}
for k, v in test_input.items():
    ret, out = testmethod(v)
    if ret:
        d[k] = out

I tried below line to iterate using lambda and map:

>>> dict(map(lambda ref: testmethod(ref), list(test_input.values())))
{True: 'Number 3'}

Expected output using map and lambda:

{'oneone': 'Number 1', 'twotwo': 'Number 2', 'threethree': 'Number 3'}

CodePudding user response:

You can rewrite your loop as follows:

d = {}
for k, v in test_input.items():
    tup = testmethod(v)
    if tup[0]:
       d[k] = tup[1]

The key is that packing and unpacking the two return values is distracting you from the fact that they are actually one return value.

Combine this insight with the walrus operator to merge the assignment and conditional lines:

if (tup := testmethod(v))[0]:

Now you have something shaped like a dictionary comprehension:

d = {k: tup[1] for k, v in test_input.items() if (tup := testmethod(v))[0]}

If you have an older version of python (pre-3.8), or want to avoid using the walrus for some other reason, you need to filter the result. Your lambda is misplaced: lambda ref: testmethod(ref) is just testmethod with extra steps. The trick is to split the streams after you did the mapping. You can then filter with something like itertools.compress:

from itertools import compress

rets, outs = zip(*map(testmethod, test_input.values()))
d = dict(compress(zip(test_input.keys(), outs), rets))

This is a fairly ugly and inefficient two-liner. You can make it a lot worse as a one liner. To do that, you turn rets, outs into a list, reverse it, and expand it into a zip after test_input.keys() to make an iterator that yields key, value, filter:

d = {k: v for k, v, tf in zip(test_input. keys(), *list(zip(*map(testmethod, test_input.values())))[::-1]) if tf}

CodePudding user response:

IIUC, you want to get add a string to dict values using lambda and map. You can do:

out = dict(map(lambda x: (x[0], 'Number'   str(x[1])), test_input.items()))

Output:

{'oneone': 'Number1', 'twotwo': 'Number2', 'threethree': 'Number3'}

Now, if we insist on using testmethod, we can tweak the above lambda a bit as

out = dict(map(lambda x: (x[0], testmethod(x[1])), test_input.items()))

Output:

Number 1
Number 2
Number 3
{'oneone': 'Number 1', 'twotwo': 'Number 2', 'threethree': 'Number 3'}

  • Related