2010-03-25 6 views

답변

86
>>> a = range(1, 10) 
>>> [x for x in a if x not in [2, 3, 7]] 
[1, 4, 5, 6, 8, 9] 
+7

내가리스트'[1,2,2,2,3,4]'와 하위 목록을 한 경우'[2,3]', 결과는 [1,2,2,4 '해야한다 무엇 ]', 거기에 파이썬 적 방법이 있습니까? – user

+0

@user 이렇게하면 대부분의 방법을 얻을 수 있지만 문제는 다른 문제입니다! l = [1,2,2,3,4] sl = [2,3] [x는 범위 (0, len (l))의 n에 대해 [l [n : n + 2] :: 2]] if x! = sl] – jsh

11
a = range(1,10) 
itemsToRemove = set([2, 3, 7]) 
b = filter(lambda x: x not in itemsToRemove, a) 

또는

b = [x for x in a if x not in itemsToRemove] 

lambda 내부 또는 이해 내부 세트를 만들지 마십시오. 그렇게하면 모든 반복마다 다시 작성되어 세트를 사용하지 않을 수 있습니다.

+1

N 세트를 생성하는 것을 제외하고, N은 len (a)입니다. – FogleBird

+0

람다 함수 –

+0

좋은 점, FogleBird 생성시 하나의 세트 만 생성합니다. 람다 또는 목록 이해력 밖에서 그것을 만들어야합니다. – Yaroslav

5

다른 사람은 필터링 후 새 목록을 만드는 방법을 제안했습니다.

newl = [x for x in l if x not in [2,3,7]] 

또는

newl = filter(lambda x: x not in [2,3,7], l) 

하지만 귀하의 질문에서 원래 목록이 긴 항목의 경우 당신이 자리에서이 작업을 수행 할 수 있습니다에 대한 수정이도 훨씬 빠른 될 것입니다 원하는 보인다 제거해야 할 이하

l = range(1,10) 
for o in set([2,3,7,11]): 
    try: 
     l.remove(o) 
    except ValueError: 
     pass 

print l 

출력 : [1, 4, 5, 6, 8, 9

ValueError 예외가 있는지 확인하여 항목이 원래 목록에 없더라도 작동합니다.

또한 적절한 수정이 필요없는 경우 S.Mark을 사용하면 더 간단합니다.

+0

실제 수정이 필요한 경우 이전 답변을 다음과 같이 수정할 수 있습니다. [a [:] = [x는 [x] [x] [x] [x] [2,3,7]에 없습니다. 이것은 귀하의 코드보다 빠릅니다. –

+2

예 [:]를 사용할 수는 있지만 더 빠를 것이라는 것은 분명하지 않습니다. 값이 거의없는 긴 목록에서 내 코드를 제거하는 것이 훨씬 빠릅니다. 시도 목록 제거 = [1] : –

+0

@Anurag : 당신은 옳은 것 같습니다; 타이밍 테스트를 통해 제자리에서 제거하는 것이 더 빠릅니다. –

5

가장 간단한 방법은

>>> a = range(1, 10) 
>>> for x in [2, 3, 7]: 
... a.remove(x) 
... 
>>> a 
[1, 4, 5, 6, 8, 9] 

한 가지 문제는 여기에()를 호출 할 때마다 제거한다는 것입니다, 모든 항목은 구멍을 채우기 위해 목록을 아래로 섞습니다. 따라서 a이 매우 커지면 매우 느려지 게됩니다.

이 방법은 새로운 목록을 만듭니다. 장점은 그렇게하지 않으면 우리는 당신이 장소에 a을 수정하려면, 첫 번째 방법

>>> removeset = set([2, 3, 7]) 
>>> a = [x for x in a if x not in removeset] 

의 모든 셔플을 피하기 하나의 작은 변화가

>>> removeset = set([2, 3, 7]) 
>>> a[:] = [x for x in a if x not in removeset] 
+0

@gnibbler, 귀하의 주장 * "그래서''''커지면 아주 느려지 게 될 것입니다."*는 다소 오해의 소지가 있습니다. 'a'의 길이 만 제한이없는 경우, 제공된 모든 스 니펫은 O (n)입니다. ** remove **와 관련된 ** 진짜 ** 문제는 모든 인수가 아닌 인수의 첫번째 발생 * 만 제거한다는 것입니다. 또한 일반적으로 오래된 목록을 변경하기보다는 새로운 목록을 만드는 명확하고 관용적 인 코드를 작성하는 것이 더 중요합니다. –

+0

@Mike, 나는 OP가 초보자 용 태그를 사용 했으므로 답을 간단하게 유지하려고 시도했다. –

+3

"simple"은 * wrong *에 대한 변명의 대상이 아닙니다. –

4
>>> a=range(1,10) 
>>> for i in [2,3,7]: a.remove(i) 
... 
>>> a 
[1, 4, 5, 6, 8, 9] 

>>> a=range(1,10) 
>>> b=map(a.remove,[2,3,7]) 
>>> a 
[1, 4, 5, 6, 8, 9] 
+0

부작용으로'map'을 사용하지 마십시오. 'map'은 다수의 호출 결과를 수집하기위한 것입니다. for 루프는 무언가를 무언가를하기위한 도구입니다. –

+0

부작용의 의미가'map '에 의한 "none"반환이면 "마스크"가 해제 될 수 있습니다. 그것 이외에, 그것의 아직도 유효하고, 나는 그것의 간결한 것을 좋아한다. – ghostdog74

29

을 필요가 있다는 것입니다 반복되는 값을 가지고 있다면, 차이를 사용할 수 있습니다.

x = set(range(10)) 
y = x - set([2, 3, 7]) 
# y = set([0, 1, 4, 5, 6, 8, 9]) 

그런 다음 필요에 따라 목록으로 다시 변환하십시오.

+0

이렇게하면 결과 목록이 섞일 것입니다. –

+1

목록의 순서가 결정적으로 바뀔 수 있습니다. 임의의 의미에서 "섞여"있지 않습니다. – dansalmo

+3

또한 원래 목록 x가 중복 된 경우 set() 작업 후 하나만 저장됩니다. –

14

나는 주제를 빨리 수행 할 방법을 찾고 있었기 때문에 제안 된 방법으로 몇 가지 실험을 만들었습니다. 그리고 나는 결과에 놀랐다. 그래서 나는 당신과 그것을 나누고 싶다.

실험 pythonbenchmark에게 도구 및

a = range(1,50000) # Source list 
b = range(1,15000) # Items to remove 

결과와 함께 사용하여 수행되었다 :

def comprehension(a, b): 
    return [x for x in a if x not in b] 

5 시도, 평균 시간

def filter_function(a, b): 
    return filter(lambda x: x not in b, a) 

5 시도 12.8 초, 평균 시간을 12.6 초

012 3,516,
def modification(a,b): 
    for x in b: 
     try: 
      a.remove(x) 
     except ValueError: 
      pass 
    return a 

5 시도 평균 시간

def set_approach(a,b): 
    return list(set(a)-set(b)) 

5 시도 0.27 초 평균 시간 0.0057 초 또한

내가 지난 2 개 기능 큰 입력의 크기와 다른 측정했다

a = range(1,500000) 
b = range(1,100000) 

결과 :

수정 (방법 제거)에 대한

- 평균 시간 설정 방법에 대한 2백52초 이다 - 평균 시간은 그래서 당신은 세트와 그 접근 방식입니다 볼 수 있습니다 0.75

입니다 크게 다른 사람보다 더 빨리. 예, 비슷한 항목을 유지하지 않지만 필요하지 않은 경우 - 그것은 당신을위한 것입니다. 목록 이해력과 필터 함수 사용 간에는 거의 차이가 없습니다. '제거'사용은 50 배 빠르지 만 소스 목록을 수정합니다. 그리고 세트를 사용하는 것이 가장 좋습니다. 목록 이해보다 1000 배 이상 빠릅니다!

+0

매우 흥미 롭습니다. 나는 세트를 사용하지 않았을 것이다. 직관적으로 변환은 오버 헤드를 추가해야한다. 분명히 내 직감이 틀렸다. 통찰력에 감사드립니다. – lhk

관련 문제