나는 이것과 비슷한 것을하고 싶다 :
>>> x = [1,2,3,4,5,6,7,8,9,0]
>>> x
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
>>> y = [1,3,5,7,9]
>>> y
[1, 3, 5, 7, 9]
>>> y - x # (should return [2,4,6,8,0])
그러나 이것은 파이썬 목록에서 지원하지 않습니다. 가장 좋은 방법은 무엇입니까?
답변
목록 이해력을 사용하십시오.
[item for item in x if item not in y]
-
infix 구문 을 사용하려면 다음을 수행하십시오.
class MyList(list):
def __init__(self, *args):
super(MyList, self).__init__(args)
def __sub__(self, other):
return self.__class__(*[item for item in self if item not in other])
그런 다음 다음과 같이 사용할 수 있습니다.
x = MyList(1, 2, 3, 4)
y = MyList(2, 5, 2)
z = x - y
그러나 목록 속성 (예 : 순서)이 절대적으로 필요하지 않은 경우 다른 답변에서 권장하는대로 세트를 사용하십시오.
답변
답변
이것은 “세트 빼기”연산입니다. 이를 위해 설정된 데이터 구조를 사용하십시오.
파이썬 2.7에서 :
x = {1,2,3,4,5,6,7,8,9,0}
y = {1,3,5,7,9}
print x - y
산출:
>>> print x - y
set([0, 8, 2, 4, 6])
답변
중복 및 주문 품목에 문제가있는 경우 :
[i for i in a if not i in b or b.remove(i)]
a = [1,2,3,3,3,3,4]
b = [1,3]
result: [2, 3, 3, 3, 4]
답변
많은 사용 사례에서 원하는 답변은 다음과 같습니다.
ys = set(y)
[item for item in x if item not in ys]
이것은 aaronasterling의 답변 과 quantumSoup의 답변 사이의 하이브리드 입니다.
aaronasterling의 버전은의 len(y)
각 요소에 대한 항목 비교를 수행 x
하므로 2 차 시간이 걸립니다. quantumSoup의 버전을 사용하는 세트는, 그래서 각 요소에 대해 하나의 일정 시간의 집합을 조회하지 x
가 변환하기 때문에, -하지만를 모두 x
와 y
세트로, 그것은 당신의 요소의 순서를 잃는다.
y
세트 로만 변환 x
하고 순서를 반복 하면 선형 시간과 순서 보존이라는 두 가지 이점을 모두 누릴 수 있습니다. *
그러나 이것은 여전히 quantumSoup의 버전에서 문제가 있습니다 : 요소를 해시 할 수 있어야합니다. 예를 들어, 다른 dicts 목록에서 dicts 목록을 빼려고하지만 뺄 목록이 큰 경우 어떻게해야합니까?
해시가 가능한 방식으로 값을 꾸밀 수 있다면 문제가 해결됩니다. 예를 들어, 값 자체가 해시 가능한 플랫 사전의 경우 :
ys = {tuple(item.items()) for item in y}
[item for item in x if tuple(item.items()) not in ys]
유형이 조금 더 복잡한 경우 (예 : 종종 해시 가능한 JSON 호환 값 또는 값이 재귀 적으로 동일한 유형 인 목록 또는 딕트를 처리하는 경우)이 솔루션을 계속 사용할 수 있습니다. 그러나 일부 유형은 해시 가능한 것으로 변환 할 수 없습니다.
아이템이 해시 가능하지 않고 해시 가능하지만 비교 가능하다면 적어도 로그 선형 시간을 얻을 수 있습니다 ( O(N*log M)
, 이는 O(N*M)
목록 솔루션 시간 보다 훨씬 좋지만 좋지는 않습니다. O(N+M)
정렬하고 사용하여 설정된 솔루션 의 시간) bisect
:
ys = sorted(y)
def bisect_contains(seq, item):
index = bisect.bisect(seq, item)
return index < len(seq) and seq[index] == item
[item for item in x if bisect_contains(ys, item)]
아이템이 해시 가능하거나 비교 가능하지 않으면 2 차 솔루션에 갇혀 있습니다.
* OrderedSet
레시피 및 타사 모듈을 찾을 수 있는 한 쌍의 객체 를 사용하여이 작업을 수행 할 수도 있습니다. 그러나 나는 이것이 더 간단하다고 생각합니다.
** 집합 조회가 일정한 시간 인 이유는 값을 해시하고 해당 해시에 대한 항목이 있는지 확인하기 때문입니다. 값을 해시 할 수 없으면 작동하지 않습니다.
답변
세트에서 값을 찾는 것이 목록에서 찾는 것보다 빠릅니다.
[item for item in x if item not in set(y)]
나는 이것이 다음보다 약간 더 잘 확장 될 것이라고 믿는다.
[item for item in x if item not in y]
둘 다 목록의 순서를 유지합니다.
답변
목록에 중복 요소가 허용되면 컬렉션의 카운터를 사용할 수 있습니다.
from collections import Counter
result = list((Counter(x)-Counter(y)).elements())
x의 요소 순서를 유지해야하는 경우 :
result = [ v for c in [Counter(y)] for v in x if not c[v] or c.subtract([v]) ]