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 값을 제거하지 않고 목록에서 없음 값을 제거하는 방법은 무엇입니까?

답변:


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사용 partial하고 operator.is_not나는 생각하지만, 그것은 너무 깨끗 아마 목록 - 완부터 그럴 가치가 없어.
mgilson

3
@ mgilson 오, 와우, 나는 is_not존재 조차 몰랐다 ! 난 그냥 생각했다 is_, 난 그냥 재미를 위해 추가 할거야
jamylak

@jamylak-네. 그것은 실제로 is_not존재하고 존재 not_in하지 않는 나를 귀찮게 합니다. 나는 실제로 그것이 not_in마법의 방법으로 바뀌어야한다고 생각한다. 나는 잠시 전에 물었던 질문과 내가 대답 한 사람에 대한 의견을__not_contains__ 보아라 .
mgilson

@ mgilson 나는 동일한 가정하에 방금 존재하지 않는다고 가정했습니다. 난 당신이 그냥 filterfalse사용 사례에 따라 사용할 수있는 것 같아요
jamylak

@jamylak-네. 내 주요 문제는 and 에서 무엇이든 할 수 있기 때문에 파이썬에서 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 마십시오 당신의 사용을 권장 __ne__반대로 그렇게 partial하고 ne?
jamylak

1
@jamylak 예, 더 빠르며, 쓰기가 더 쉽고, 좀 더 명확합니다.
Raymond Hettinger

operator모듈 사용을 고려하십시오 .
rightfold

12
무엇입니까 __ne__?
DrMcCleod

11
@DrMcCleod이 표현식은 x != y내부적으로 ne 가 "같지 않음"을 나타내는 x.__ne__(y)위치를 호출합니다 . 따라서 None 이외의 다른 값으로 호출 될 때 True 를 반환하는 바인딩 된 메서드입니다 . 예를 들어 with 로 호출하면 NotImplemented 를 true로 반환하고 False를 반환합니다 . None.__ne__bm = None.__ne__bm(10)bm(None)
Raymond Hettinger

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에 해당하는 Raymond의 답변 참조) :

"없음"이 아닌 것이 파이썬 (및 다른 OO 언어)에서 매우 일반적인지 알고 싶다면 Common.py ( "from from import *"를 사용하여 각 모듈로 가져옴)에서 다음 줄을 포함합니다.

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

그런 다음 목록에서 없음 요소를 제거하려면 다음을 수행하십시오.

filter(exists, L)

해당 목록 이해력 (레이몬드가 Python 2 버전으로 표시)보다 읽기가 더 쉽다는 것을 알았습니다.


파이썬 3에는 Raymonds 솔루션을 선호하고 파이썬 2에 대한 목록 이해력을 선호합니다. 그러나이 경로를 따라 가야한다면 partial(is_not, None)이 솔루션 보다는 오히려이 솔루션을 선호합니다 . 나는 이것이 느릴 것이라고 믿습니다 (그러나 그렇게 중요하지는 않지만). 그러나 몇 가지 파이썬 모듈을 가져 오면이 경우 사용자 정의 함수를 정의 할 필요가 없습니다
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

반복공간 , 사용량이 문제가 될 수 있습니다. 다른 상황에서 프로파일 링은 "빠른"및 / 또는 "메모리 부족"집중적 인 것으로 나타날 수 있습니다.

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

번째 접근법 ( @jamylak , @Raymond Hettinger@Dipto에 의해 제안 )은 메모리에 중복 목록을 생성합니다.None 항목을.

번째 접근 방식은 목록을 한 번 통과 한 다음 a None에 도달 할 때까지 다시 반복합니다 . 메모리 사용량이 적을 수 있으며 목록이 작을수록 작아집니다. 목록 크기가 줄어들 None면 전면에있는 많은 항목 의 속도가 빨라질 수 있지만, 많은 None항목이 후면에 있는 경우 최악의 경우입니다 .

병렬화 및 인플레 이스 기술은 다른 접근 방식이지만 각각 Python에서 자체적 인 문제가 있습니다. 데이터 및 런타임 유스 케이스를 알고 프로그램을 프로파일 링하는 작업은 집중적 인 조작 또는 대규모 데이터를 시작하는 곳입니다.

두 가지 방법 중 하나를 선택하면 일반적인 상황에서는 중요하지 않습니다. 표기법이 더 선호됩니다. 사실, 그러한 드문 상황에서, numpy또는 cython파이썬 최적화를 미세 관리하려고 시도하는 대신 가치있는 대안이 될 수 있습니다.


전혀 팬이 아니라,이 솔루션으로 주장하는 장점은 목록이 너무 커서 메모리에 중복 목록을 작성하는 데 많은 비용이들 수 있다는 것입니다. 그렇다면 전체 목록을 스캔하고 여러 번 호출 하여 솔루션 을 만드는 데 비용이 많이 듭니다. 해결하려는 상황을 이런 식으로 처리해서는 안되며 데이터를 재구성해야합니다. 메모리를 많이 사용하는 경우 대신 데이터베이스 또는 파일로. L.count(None).remove(None)O(N^2)
jamylak

@jamylak 사실이지만 모든 실제 상황이나 데이터가 그러한 유연성을 허용하지는 않습니다. 예를 들어, 많은 메모리가없는 시스템에서 일회성 분석을 통해 "레거시"지리 공간 데이터를 펌핑합니다. 그런 다음 고려해야 할 프로그래밍 시간과 런타임도 있습니다. 개발 시간이 단축되어 사람들은 종종 파이썬을 사용합니다. 이 답변을 통해 기억력을 고려할 가치가 있다는 사실에 주목하고 있지만, 결국에는 개인별로 선호하는 표기법이라고 말하고 싶습니다. 또한 데이터를 아는 것이 중요하다고 지적합니다. O(n^2)전체 목록이 인 경우에만 해당됩니다 None.
케빈

이 답변이 최선의 해결책 인 실용적인 사례가 있다면 관심이 있으리라 생각합니다. 모든 경우에 더 나은 접근 방식이 있다고 생각하는 경향이 있습니다. 예를 들어 numpy이러한 유형의 작업을보다 최적화 된 방식으로 처리 할 수 ​​있습니다.
jamylak

@jamylak 공정하게 말하면, numpy최근 몇 년 동안 사용해 왔지만 별도의 기술입니다. 경우 LA와 인스턴스화 numpy.array대신 파이썬 list, 다음 L = L[L != numpy.array(None)](stackoverflow.com/a/25255015/3003133는) 아마도 더 나은 하나보다,하지만 난 메모리 아래에 대 처리 구현 세부 사항을 알고하지 않습니다. 최소한 마스크에 대해 중복 길이의 부울 배열을 작성합니다. 그런 식으로 액세스 (인덱스) 연산자 내부의 비교 구문은 처음입니다. 이 토론은 또한 나의 관심을 끌었다 dtype=object.
케빈

이 토론은 이제 너무 추상적이되고 있습니다. 수년 간의 경험 에서이 답변이 이전에 언급 한 데이터 구조 조정에 대한 올바른 접근 방법이라는 실제 사례를 제시 할 수는 없다고 생각합니다.
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

글쎄, 이것은 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] ) ) 그러나 파이썬 2의 경우

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

<< 변수가 None이 아닌 경우 List의 변수에 대한 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.