9

I am using map to process a list in Python3.6:

def calc(num):
    if num > 5:
        return None
    return num * 2


r = map(lambda num: clac(num), range(1, 10))
print(list(r))

# => [2, 4, 6, 8, 10, None, None, None, None]

The result I expect is: [2, 4, 6, 8, 10].

Of course, I can use filter to handle map result. But is there a way for map to return directly to the result I want?

Georgy
  • 12,464
  • 7
  • 65
  • 73
Martin Zhu
  • 421
  • 3
  • 13

2 Answers2

13

map cannot directly filter out items. It outputs one item for each item of input. You can use a list comprehension to filter out None from your results.

r = [x for x in map(calc, range(1,10)) if x is not None]

(This only calls calc once on each number in the range.)

Aside: there is no need to write lambda num: calc(num). If you want a function that returns the result of calc, just use calc itself.

khelwood
  • 55,782
  • 14
  • 81
  • 108
  • Thanks, relative list comphrenension, filter may be a better solution: `r = filter(lambda r: r is not None, map(lambda num: clac(num), range(1, 10)))`? – Martin Zhu Jul 05 '18 at 11:32
  • 1
    @MartinZhu, Actually, the list comprehension will likely perform better. In general, `filter` + `lambda` / `map` + `lambda` should be avoided in favour of list comprehensions. – jpp Jul 05 '18 at 11:43
0

Not when using map itself, but you can change your map() call to:

r = [calc(num) for num in range(1, 10) if calc(num) is not None]
print(r)  # no need to wrap in list() anymore

to get the result you want.

viraptor
  • 33,322
  • 10
  • 107
  • 191
  • @spejsy Only is this specific case though. In real-world cases you may not know which `num` produces a `None` response. – viraptor Jul 05 '18 at 11:16
  • What I want to filter is calc(num), not num. – Martin Zhu Jul 05 '18 at 11:17
  • 1
    thanks, `[calc(num) for num in range(1, 10) if calc(num) is not None]` can work, but the same element in the list will be processed twice. Is there a way to optimize this? – Martin Zhu Jul 05 '18 at 11:22