0値を削除せずにリストからNone値を削除します


244

これは私が始めた私のソースでした。

私のリスト

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

これを実行すると:

L = filter(None, L)

私はこの結果を得ます

[23, 234, 89, 35, 9]

しかし、これは私が必要とするものではありません、私が本当に必要なのは:

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

私はデータのパーセンタイルを計算しているので、0は多くの違いを生みます。

0値を削除せずにリストからNone値を削除する方法は?

回答:


354
>>> 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]

面白くするためfilterに、を使用せずにこれを行うためにどのように適応できるかを示しますlambda(このコードはお勧めしません-科学的な目的のみです)

>>> from operator import is_not
>>> from functools import partial
>>> L = [0, 23, 234, 89, None, 0, 35, 9]
>>> filter(partial(is_not, None), L)
[0, 23, 234, 89, 0, 35, 9]

23
あまりエレガントfilterバージョン: filter(lambda x: x is not None, L)-あなたは取り除くことができlambda使用するpartialoperator.is_not、私は思いますが、リスト-COMPはそんなにきれいであるので、それはおそらく、それだけの価値はありません。
mgilson 2013

3
@mgilsonああすごいis_not存在すら知らなかった!それだけだと思ったのでis_、楽しみに追加します
jamylak 2013

@jamylak-ええ。それは実際に私を悩ますis_not存在し、not_in存在しません。私は実際にそれnot_inを魔法の方法に変えるべきだと思います__not_contains__... しばらく前に尋ねた質問と回答者に加えたコメントを参照してください...それでも解決されたようには感じません。
mgilson 2013

@mgilsonその同じ仮定の下で、私はそれが存在しないと仮定しただけだと思います。filterfalseユースケースに応じて、単に使用することも、何かを使用することもできると思います
jamylak

@jamylak-ええ。私の主な問題は、とで何でもできるのでpythonをx > y意味しないことnot x <= yです。それで、(特に、独自のバイトコードがあるので)意味する必要があります__lt____le__x not in ynot x in ynot in
mgilson

136

FWIW、Python 3はこの問題を簡単にします。

>>> L = [0, 23, 234, 89, None, 0, 35, 9]
>>> list(filter(None.__ne__, L))
[0, 23, 234, 89, 0, 35, 9]

Python 2では、代わりにリスト内包表記を使用します。

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

+1 andと__ne__は対照的にpartial、そのような使用をお勧めしますneか?
jamylak 2013

1
@jamylakはい、それはより速く、少し書きやすく、もう少し明確です。
レイモンドヘッティンガー2013

operatorモジュールの使用を検討してください。
2015

12
なに__ne__
DrMcCleod 2017

11
@DrMcCleod式は、neが「等しくない」を表す場所をx != y内部的に呼び出します。したがって、None以外の値で呼び出されたときにTrueを返すバインドされたメソッドです。例えば、と呼ばれる戻りNotImplemented真の値としてこれを、して返しますFalseをx.__ne__(y)None.__ne__bm = None.__ne__bm(10)bm(None)
レイモンドヘッティンガー2017

17

リスト内包表記を使用すると、次のように行うことができます。

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

lの値は次のとおりです。

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

この解決策はすでにトップアンサーにありますか、それとも何か不足していますか?
Qaswed、

16

Python 2.7の場合(レイモンドの回答を参照、Python 3の同等の場合):

「Noneではない」ものがPython(および他のOO言語)で一般的であるか、Common.py(「from Common import *」を使用して各モジュールにインポートする)でそうであるかどうかを知りたいので、次の行を含めます。

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

次に、リストからNone要素を削除するには、次のようにします。

filter(exists, L)

これは、対応するリスト内包表記(Raymondが彼のPython 2バージョンとして示している)よりも読みやすいと思います。


私はPython 3のレイモンドソリューションを好み、次にPython 2のリスト内包を好みます。しかし、このルートに行かなければならない場合は、むしろ partial(is_not, None)、このソリューションでます。私はこれが遅くなると信じています(それはあまり重要ではありませんが)。しかし、pythonモジュールの輸入のカップル、この場合は、カスタム定義された機能を必要とせず、
jamylak

12

@jamylakの回答は非常に優れていますが、この単純なタスクを実行するためだけにいくつかのモジュールをインポートしたくない場合は、独自のlambdaインプレースを作成します。

>>> L = [0, 23, 234, 89, None, 0, 35, 9]
>>> filter(lambda v: v is not None, L)
[0, 23, 234, 89, 0, 35, 9]

あなたは明らかに私の解決策を正しく読みませんでした。これは[x for x in L if x is not None]他のコードが私が推奨しないと明示的に述べた単なる追加でした
jamylak

1
@jamylak-私はそれを読みましたが、あなたはこの解決策を含んでいませんでした。-また、4〜5年前の人の回答を編集する理由がわかりません。
AT

5

反復 vs スペース、使用法が問題になる可能性があります。さまざまな状況で、プロファイリングは「より高速」または「メモリ不足」のどちらかが集中的に発生する場合があります。

# 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, ...]

最初のアプローチは、(ASによっても示唆@jamylak@Raymondヘッティンガー、及び@Dipto)少数で大規模なリストのために費用がかかる可能性があり、メモリ内の複製リストを作成しますNoneのエントリを。

第二のアプローチは、一度リストを通過した後、再びまでの各時間がNone到達しています。これはメモリをあまり消費しない可能性があり、リストは小さくなるにつれて小さくなります。リストのサイズを小さくするNoneと、前のエントリの数が増える可能性がありますが、最悪のケースは、None、背面にエントリがです。

並列化とインプレーステクニックは他のアプローチですが、Pythonではそれぞれ独自の問題があります。データとランタイムのユースケースを理解し、プログラムをプロファイリングすることは、集中的な操作または大きなデータの開始点です。

どちらの方法を選択しても、一般的な状況ではおそらく問題になりません。表記の方が好みになります。実際には、これらの珍しい状況で、numpyまたはcython代わりにmicromanage Pythonの最適化しようとする価値のある選択肢かもしれません。


これのファンではありません。このソリューションであなたが主張する全体的な利点は、リストが非常に大きく、メモリ内に重複したリストを作成するとコストがかかる可能性があることです。それでは、リスト全体をスキャンしてから複数回呼び出すため、ソリューションのコストはさらに高くL.count(None)なります。.remove(None)これによりO(N^2)、解決しようとしている状況はこのように処理されるべきではなく、データは再構築されるべきですメモリを大量に消費する場合は、代わりにデータベースまたはファイルに保存します。
jamylak

@jamylak真実ですが、現実の状況やデータのすべてがその柔軟性を可能にするわけではありません。たとえば、メモリの少ないシステムでの1回限りの分析による「レガシー」地理空間データのポンプ。次に、考慮すべきプログラミング時間と実行時間もあります。開発時間の節約のため、人々はしばしばPythonに目を向けます。この答えで、私は記憶が考慮に値するかもしれないという事実に注意を向けています、しかし私は最後にそれが記法のほとんど個人的な好みであると述べます。また、データを知ることが重要であることも指摘します。O(n^2)リスト全体がの場合のみですNone
ケビン

この答えが最良の解決策である実際的な例がある場合、興味がありますが、すべてのケースでより良いアプローチがあると思いがちです。たとえば、numpyこのタイプの操作をより最適化された方法で処理できます
jamylak

@jamylak公平に言うと、私はnumpy近年使用していますが、それは別のスキルです。もしLnumpy.arrayPythonではなくとしてインスタンス化されているlistL = L[L != numpy.array(None)](stackoverflow.com/a/25255015/3003133)はおそらくどちらよりも優れていますが、その下の処理とメモリの実装の詳細はわかりません。少なくとも、マスクに対してブール値の複製の長さ配列を作成します。このように、アクセス(インデックス)演算子内の比較の構文は、私にとっては初めてです。この議論は私の注目を集めましたdtype=object
ケビン

このディスカッションは抽象化しすぎています。これまでの長年の経験の中で、私が前に述べたようにこの回答がデータの再構築に対する正しいアプローチである実例を1つ挙げることはできないと思います。
jamylak

2
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))

6
コードだけでなく、OPに詳細情報を提供してください。
Laurent LAPORTE

1
やった。あなたが思うこと?
med_abidi 2016年

まあ、これはOPの質問には答えません。代わりにこの回答を検討してください:stackoverflow.com/a/16096769/1513933
Laurent LAPORTE

はい、あなたは正しいです。フィルター部分に問題がありました。
med_abidi

2

それがすべてリストのリストである場合は、@ Raymond先生の回答を変更できます。

L = [ [None], [123], [None], [151] ] no_none_val = list(filter(None.__ne__, [x[0] for x in L] ) ) ただし、Python 2の場合

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

<<変数がNoneでない場合、リスト内の変数のlist_indice [0] >>


1

リストは以下のようだとしましょう

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

これは、 bool(item) is True

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

これは

print [item for item in iterator if item]

なしのみをフィルタリングするには:

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

に相当:

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

Falseと評価されるすべてのアイテムを取得するには

print filter(lambda item: not item, iterator)
# Will print [None, '', 0, None, False, {}, (), []]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.