21

I need to build a list from a string in python using the [f(char) for char in string] syntax and I would like to be able to ignore (not insert in the list) the values of f(x) which are equal to None.

How can I do that ?

ronan_mac
  • 428
  • 7
  • 16
Mat
  • 1,022
  • 2
  • 9
  • 24

2 Answers2

40

We could create a "subquery".

[r for r in (f(char) for char in string) if r is not None]

If you allow all False values (0, False, None, etc.) to be ignored as well, filter could be used:

filter(None, (f(char) for char in string) )
# or, using itertools.imap,
filter(None, imap(f, string))
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • 1
    I like the first one, thanks! Very clean to just build an iterable as the intermediate. I have been doing either two lines, or `[f(x) for x in l if f(x) is not None]`, unnecessarily performing the op twice. – Luke Davis Feb 21 '17 at 04:53
  • @luke-davis, not realy if you use something called memoization. But it's still not elegance. – Christoforus Surjoputro Jan 25 '19 at 03:21
0

You can add a conditional in the for, to check of each element is not None or empty

[element for element in list_of_elements) if element]

this allow to avoid a double looping

Example. Remove even numbers from a list:

f = lambda x: x % 2
list_of_elements = [1, 2, 3, 4, 5, 7, 34, 45, 55, 65, 66]
c = [element for element in list_of_elements if f(element)]

Output:

[1, 3, 5, 7, 45, 55, 65]
Crandel
  • 767
  • 6
  • 10
  • This is not really what this question was about. I want(ed) to remove elements from a list *after* some transformation `f` was applied, based on the result of the transformation, but without having to call the transform function `f` twice on very element. Your solution does not answer that. And is not syntactically valid either. – Mat Feb 07 '23 at 10:17
  • Since this is all using iterators, there is no "double looping" involved in the accepted answer. – Mat Feb 07 '23 at 10:18
  • There are two nested for loops in the above answer. I added an example – Crandel Feb 14 '23 at 18:32