326

This was my source I started with.

My List

L = [0, 23, 234, 89, None, 0, 35, 9]

When I run this :

L = filter(None, L)

I get this results

[23, 234, 89, 35, 9]

But this is not what I need, what I really need is :

[0, 23, 234, 89, 0, 35, 9]

Because I'm calculating percentile of the data and the 0 make a lot of difference.

How to remove the None value from a list without removing 0 value?

Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
mongotop
  • 7,114
  • 14
  • 51
  • 76

11 Answers11

487
>>> L = [0, 23, 234, 89, None, 0, 35, 9]
>>> [x for x in L if x is not None]
[0, 23, 234, 89, 0, 35, 9]

Just for fun, here's how you can adapt filter to do this without using a lambda, (I wouldn't recommend this code - it's just for scientific purposes)

>>> from operator import is_not
>>> from functools import partial
>>> L = [0, 23, 234, 89, None, 0, 35, 9]
>>> list(filter(partial(is_not, None), L))
[0, 23, 234, 89, 0, 35, 9]
jamylak
  • 128,818
  • 30
  • 231
  • 230
  • 27
    The less elegant `filter` version: `filter(lambda x: x is not None, L)` -- You could get rid of the `lambda` using `partial` and `operator.is_not` I think, but it's probably not worth it since the list-comp is so much cleaner. – mgilson Apr 19 '13 at 03:36
  • 6
    @mgilson Oh wow I didn't even know `is_not` existed! I thought it was only `is_`, I'm gonna add that in just for fun – jamylak Apr 19 '13 at 03:40
  • @jamylak -- Yeah. It actually bothers me that `is_not` exists and `not_in` doesn't exist. I actually think that `not_in` should be turned into a magic method `__not_contains__` ... see a [question](http://stackoverflow.com/questions/11435206/python-operator-no-operator-for-not-in) I asked a while back and a [comment](http://stackoverflow.com/questions/11435206/python-operator-no-operator-for-not-in#comment15128009_11435319) I made to an answerer ... and still don't feel like it is resolved. – mgilson Apr 19 '13 at 03:47
  • @mgilson I think under that same assumption I just assumed it didn't exist. I guess you can just use `filterfalse` or something depending on the use case – jamylak Apr 19 '13 at 03:58
  • @jamylak -- Yeah. My main problem is that `x > y` does not imply `not x <= y` in python because you can do anything in `__lt__` and `__le__`, so why should `x not in y` imply `not x in y` (especially since `not in` has it's own bytecode?) – mgilson Apr 19 '13 at 04:07
  • @mgilson right, that's a good point, Python isn't perfect though – jamylak Apr 19 '13 at 04:08
  • What does partial do in here? – matt.aurelio Jul 15 '22 at 16:56
  • @matt.aurelio It creates a new function, that calls `is_not` with the 1st parameter always set to `None` so it will be like`is_not(None, ...)` so the first filter will try `is_not(None, 0)` which is `False` so `0` will be part of the resulting list. Then filter will try `is_not(None, 23)` which will be `False` so add `23` to the resulting list, and so on. Since `filter` takes a function to filter by and in this case we want to check `is not None`. We could also do `filter(lambda x: x is not None, L)` but the list comprehension is nicer than that, and `lambda`s are generally hefty and slow – jamylak Jul 15 '22 at 22:28
  • I have one similar question like this. I have 2 lists same length and different data types.how can we pop None type elements by comparing two lists. If 1 list having None at index 5 then we will pop the 5th element from both the list and similarly if none in list2. How can we pop. – Amarnath Reddy Surapureddy Aug 10 '22 at 15:08
  • @AMAR This is a very specific issue, you can create a new question for this on StackOverflow but make sure to include your initial attempt at solving it – jamylak Aug 10 '22 at 23:15
  • @jamyalk Sir I got the answer from above suggestion. – Amarnath Reddy Surapureddy Aug 11 '22 at 06:13
162

A list comprehension is likely the cleanest way:

>>> L = [0, 23, 234, 89, None, 0, 35, 9
>>> [x for x in L if x is not None]
[0, 23, 234, 89, 0, 35, 9]

There is also a functional programming approach but it is more involved:

>>> from operator import is_not
>>> from functools import partial
>>> L = [0, 23, 234, 89, None, 0, 35, 9]
>>> list(filter(partial(is_not, None), L))
[0, 23, 234, 89, 0, 35, 9]
Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
  • +1 Do you recommend the use of `__ne__` like that as opposed to `partial` and `ne`? – jamylak Apr 21 '13 at 01:38
  • 1
    @jamylak Yes, it is faster, a bit easier to write, and a bit more clear. – Raymond Hettinger Apr 21 '13 at 01:50
  • 2
    Consider using the [`operator`](https://docs.python.org/3.4/library/operator.html) module. –  Feb 17 '15 at 15:41
  • 12
    What is `__ne__`? – DrMcCleod Jul 12 '17 at 21:00
  • 11
    @DrMcCleod The expression ``x != y`` internally calls ``x.__ne__(y)`` where the *ne* stands for "not equal". So, ``None.__ne__`` is a bound method that returns *True* when called with any value other than *None*. For example, ``bm = None.__ne__`` called with ``bm(10)`` returns *NotImplemented* which as true value, and ``bm(None)`` returns *False*. – Raymond Hettinger Jul 13 '17 at 04:12
  • if only `M = L.filter(None)` – Marc May 04 '18 at 02:17
  • 1
    That `NotImplemented` is true in boolean context is really bizarre. See [Make NotImplemented unusable in boolean context](https://bugs.python.org/issue35712) Python issue. – Piotr Dobrogost Sep 30 '20 at 10:55
  • 1
    Python 3.9 says: `DeprecationWarning: NotImplemented should not be used in a boolean context` – Michel de Ruiter Nov 09 '20 at 11:51
25

Using list comprehension this can be done as follows:

l = [i for i in my_list if i is not None]

The value of l is:

[0, 23, 234, 89, 0, 35, 9]
jamylak
  • 128,818
  • 30
  • 231
  • 230
DotPi
  • 3,977
  • 6
  • 33
  • 53
17

For Python 2.7 (See Raymond's answer, for Python 3 equivalent):

Wanting to know whether something "is not None" is so common in python (and other OO languages), that in my Common.py (which I import to each module with "from Common import *"), I include these lines:

def exists(it):
    return (it is not None)

Then to remove None elements from a list, simply do:

filter(exists, L)

I find this easier to read, than the corresponding list comprehension (which Raymond shows, as his Python 2 version).

ToolmakerSteve
  • 18,547
  • 14
  • 94
  • 196
  • I would prefer Raymonds solution for Python 3, and then the list comprehension for Python 2. But if I did have to go this route, I would rather `partial(is_not, None)` than this solution. I believe this will be slower (although thats not too important). But with a couple of imports of python modules, no need for a custom defined function in this case – jamylak Feb 17 '18 at 14:25
  • The custom defined function isn't merely for this case. I wouldn't have defined a function if it were! I'm saying that I find it more readable, in many situations, to say "if exists(something)", instead of saying "if something is not None". Its closer to how I think, and avoids the "double-negative" of saying "not None". – ToolmakerSteve May 08 '21 at 18:10
  • I see what you mean about avoiding the double negative, actually in the definition of `exists` `return (it is not None)` is a clear way to define it. (maybe I'd remove the brackets but that's just a small thing anyway) – jamylak May 10 '21 at 03:54
17

@jamylak answer is quite nice, however if you don't want to import a couple of modules just to do this simple task, write your own lambda in-place:

>>> L = [0, 23, 234, 89, None, 0, 35, 9]
>>> filter(lambda v: v is not None, L)
[0, 23, 234, 89, 0, 35, 9]
A T
  • 13,008
  • 21
  • 97
  • 158
6

Iteration vs Space, usage could be an issue. In different situations profiling may show either to be "faster" and/or "less memory" intensive.

# first
>>> L = [0, 23, 234, 89, None, 0, 35, 9, ...]
>>> [x for x in L if x is not None]
[0, 23, 234, 89, 0, 35, 9, ...]

# second
>>> L = [0, 23, 234, 89, None, 0, 35, 9]
>>> for i in range(L.count(None)): L.remove(None)
[0, 23, 234, 89, 0, 35, 9, ...]

The first approach (as also suggested by @jamylak, @Raymond Hettinger, and @Dipto) creates a duplicate list in memory, which could be costly of memory for a large list with few None entries.

The second approach goes through the list once, and then again each time until a None is reached. This could be less memory intensive, and the list will get smaller as it goes. The decrease in list size could have a speed up for lots of None entries in the front, but the worst case would be if lots of None entries were in the back.

The second approach would likely always be slower than the first approach. That does not make it an invalid consideration.

Parallelization and in-place techniques are other approaches, but each have their own complications in Python. Knowing the data and the runtime use-cases, as well profiling the program are where to start for intensive operations or large data.

Choosing either approach will probably not matter in common situations. It becomes more of a preference of notation. In fact, in those uncommon circumstances, numpy (example if L is numpy.array: L = L[L != numpy.array(None) (from here)) or cython may be worthwhile alternatives instead of attempting to micromanage Python optimizations.

Kevin
  • 2,234
  • 2
  • 21
  • 26
  • 2
    Not a fan of this at all, the whole advantage you claim with this solution is that the list might be **so huge** that building duplicate list in memory could be costly. Well then your solution will be **even more costly** because you're scanning the entire list for `L.count(None)` and then you're calling `.remove(None)` multiple times which makes this `O(N^2)` The situation you are trying to solve should not be dealt with in this way, the data should be restructured into a Database or file instead if it's that memory intensive. – jamylak Feb 17 '18 at 14:31
  • Would be interested if you had a practical example where this answer is the best solution, I tend to think that there would be a better approach in all cases. For example `numpy` would be able to handle this type of operation in a more optimised manner – jamylak Feb 19 '18 at 05:16
  • This discussion is getting too abstract now, I don't think you'd be able to give me one real life example in your years of experience where this answer is the correct approach over restructuring the data as i mentioned before. – jamylak Feb 20 '18 at 05:39
  • True, but not all real world situations allow flexibility of transforming the data. For example, pumping "legacy" geospatial data through a one-off analysis on a system without much memory. Another example is programming time vs runtime. Might not care if something takes all night to run so long as it was inexpensive to write. What about if writing a plugin or library? You may not be the one deciding what the data looks like. With this answer, I am bringing attention to considering memory and knowing the data, but I point out it probably does not matter most of the time. – Kevin Aug 07 '20 at 19:09
  • Best-case is `O(n)`. Count n with nothing found. All `None` would be `O(2n)`. Count == n ops; then each remove comparison is found on the first item, so total comparisons is n. A single None at the end of the list is also `O(2n)`. Count is n; one additional pass through the list until None is found in the last position n. So, I think worst-case is when the back half the list is entirely None. I think that is `O(n + ((n / 2) + 1)^2)`. Another real world scenario is embedded systems with tiny amounts of memory. Micropython exists specifically for those. – Kevin Aug 07 '20 at 19:29
  • Presumably "# second" needs logic to handle ValueError, indicating there were no more to remove. – ToolmakerSteve Dec 17 '20 at 23:28
  • @ToolmakerSteve, no need the "second" because the end-case logic is covered by only removing the number of `L.count(None)` items. It cannot make extra calls to `remove`. – Kevin Dec 19 '20 at 00:10
  • It seems like the in-place approach would be better as `w=0; for e in L: if e is not None: L[w] = e; w += 1; del L[w:]`. (Sorry, I don't know how to format that in a comment. You can't really do one-line Python. The `del` is after the loop.) It's in-place and O(n). θ(n) in fact. – sfink Aug 25 '21 at 15:25
  • @sfink, that is a viable in-place implementation. That takes the implicit list restructuring out of the List.remove() operation and does it explicitly. I think by switching to `is None` and using a front and a back pointer, instead of only one, you could get rid of the redundant assignments. The my answer is simply pointing out that sometimes memory size may need to be taken into account, and not only processor operation counts. – Kevin Aug 26 '21 at 16:38
5

Say the list is like below

iterator = [None, 1, 2, 0, '', None, False, {}, (), []]

This will return only those items whose bool(item) is True

print filter(lambda item: item, iterator)
# [1, 2]

This is equivalent to

print [item for item in iterator if item]

To just filter None:

print filter(lambda item: item is not None, iterator)
# [1, 2, 0, '', False, {}, (), []]

Equivalent to:

print [item for item in iterator if item is not None]

To get all the items that evaluate to False

print filter(lambda item: not item, iterator)
# Will print [None, '', 0, None, False, {}, (), []]
theBuzzyCoder
  • 2,652
  • 2
  • 31
  • 26
3
from operator import is_not
from functools import partial   

filter_null = partial(filter, partial(is_not, None))

# A test case
L = [1, None, 2, None, 3]
L = list(filter_null(L))
med_abidi
  • 119
  • 2
  • 5
3

If it is all a list of lists, you could modify sir @Raymond's answer

L = [ [None], [123], [None], [151] ] no_none_val = list(filter(None.__ne__, [x[0] for x in L] ) ) for python 2 however

no_none_val = [x[0] for x in L if x[0] is not None] """ Both returns [123, 151]"""

<< list_indice[0] for variable in List if variable is not None >>

Skrmnghrd
  • 558
  • 4
  • 10
3
L = [0, 23, 234, 89, None, 0, 35, 9] 
result = list(filter(lambda x: x is not None, L))
rautamiekka
  • 251
  • 2
  • 14
2

If the list has NoneType and pandas._libs.missing.NAType objects than use:

[i for i in lst if pd.notnull(i)]
j__carlson
  • 1,346
  • 3
  • 12
  • 20