순서에 관계없이 두 목록에 동일한 요소가 있는지 확인합니까? [복제]
이 질문에 이미 답변이 있습니다.
간단한 질문에 대해 죄송하지만 답을 찾기가 어렵습니다.
두 목록을 비교할 때 내용은 같지만 순서가 다르다는 점에서 "동일"한지 알고 싶습니다.
전의:
x = ['a', 'b']
y = ['b', 'a']
나는 x == y
평가 하고 싶다 True
.
x와 y의 요소가있는 다중 집합이 같은지 간단히 확인할 수 있습니다.
import collections
collections.Counter(x) == collections.Counter(y)
이를 위해서는 요소가 해시 가능해야합니다. 런타임에있을 것입니다 O(n)
경우, n
목록의 크기입니다.
요소도 고유 한 경우 집합으로 변환 할 수도 있습니다 (동일한 점근 런타임이 실제로는 조금 더 빠를 수 있음).
set(x) == set(y)
요소를 해시 할 수 없지만 정렬 할 수있는 경우 다른 대안 (의 런타임 O(n log n)
)은 다음과 같습니다.
sorted(x) == sorted(y)
요소가 해시 할 수없고 정렬 할 수없는 경우 다음 도우미 함수를 사용할 수 있습니다. 그것은 (매우 느린 될 것이라고 주 O(n²)
) 일반적으로해야 하지 unhashable 및 unsortable 요소의 난해한 케이스의 외부 사용.
def equal_ignore_order(a, b):
""" Use only when elements are neither hashable nor sortable! """
unmatched = list(b)
for element in a:
try:
unmatched.remove(element)
except ValueError:
return False
return not unmatched
순서에 관계없이 두 목록에 동일한 요소가 있는지 확인합니까?
귀하의 예에서 추론 :
x = ['a', 'b']
y = ['b', 'a']
목록의 요소가 반복되지 않을 것이며 (유일하지 않음) 해시 가능 (문자열 및 기타 특정 불변 파이썬 객체가 있음), 가장 직접적이고 계산적으로 효율적인 답변 은 Python의 내장 집합을 사용합니다 (의미 적으로 수학과 유사 함). 학교에서 배운 세트).
set(x) == set(y) # prefer this if elements are hashable
요소가 해시 가능하지만 고유하지 않은 경우 collections.Counter
는 의미 상 다중 집합으로도 작동하지만 훨씬 느립니다 .
from collections import Counter
Counter(x) == Counter(y)
사용 선호 sorted
:
sorted(x) == sorted(y)
요소가 주문 가능한 경우. 이것은 고유하지 않거나 해시 할 수없는 상황을 설명하지만 세트를 사용하는 것보다 훨씬 느릴 수 있습니다.
경험적 실험
경험적 실험은 사람이 선호해야한다는 결론을 set
다음 sorted
. Counter
카운트 또는 다중 세트로 추가 사용과 같은 다른 것이 필요한 경우 에만 선택하십시오 .
첫 번째 설정 :
import timeit
import random
from collections import Counter
data = [str(random.randint(0, 100000)) for i in xrange(100)]
data2 = data[:] # copy the list into a new one
def sets_equal():
return set(data) == set(data2)
def counters_equal():
return Counter(data) == Counter(data2)
def sorted_lists_equal():
return sorted(data) == sorted(data2)
그리고 테스트 :
>>> min(timeit.repeat(sets_equal))
13.976069927215576
>>> min(timeit.repeat(counters_equal))
73.17287588119507
>>> min(timeit.repeat(sorted_lists_equal))
36.177085876464844
따라서 세트 비교가 가장 빠른 솔루션이고 정렬 된 목록 비교가 두 번째로 빠릅니다.
이것은 큰 목록의 경우 번거로울 수 있지만 작동하는 것처럼 보입니다.
>>> A = [0, 1]
>>> B = [1, 0]
>>> C = [0, 2]
>>> not sum([not i in A for i in B])
True
>>> not sum([not i in A for i in C])
False
>>>
However, if each list must contain all the elements of other then the above code is problematic.
>>> A = [0, 1, 2]
>>> not sum([not i in A for i in B])
True
The problem arises when len(A) != len(B)
and, in this example, len(A) > len(B)
. To avoid this, you can add one more statement.
>>> not sum([not i in A for i in B]) if len(A) == len(B) else False
False
One more thing, I benchmarked my solution with timeit.repeat, under the same conditions used by Aaron Hall in his post. As suspected, the results are disappointing. My method is the last one. set(x) == set(y)
it is.
>>> def foocomprehend(): return not sum([not i in data for i in data2])
>>> min(timeit.repeat('fooset()', 'from __main__ import fooset, foocount, foocomprehend'))
25.2893661496
>>> min(timeit.repeat('foosort()', 'from __main__ import fooset, foocount, foocomprehend'))
94.3974742993
>>> min(timeit.repeat('foocomprehend()', 'from __main__ import fooset, foocount, foocomprehend'))
187.224562545
As mentioned in comments above, the general case is a pain. It is fairly easy if all items are hashable or all items are sortable. However I have recently had to try solve the general case. Here is my solution. I realised after posting that this is a duplicate to a solution above that I missed on the first pass. Anyway, if you use slices rather than list.remove() you can compare immutable sequences.
def sequences_contain_same_items(a, b):
for item in a:
try:
i = b.index(item)
except ValueError:
return False
b = b[:i] + b[i+1:]
return not b
'Programming' 카테고리의 다른 글
main ()에서 EXIT_SUCCESS 또는 0을 반환해야합니까? (0) | 2020.08.13 |
---|---|
postgresql의 문자열 리터럴 및 이스케이프 문자 (0) | 2020.08.13 |
Any, AnyVal, AnyRef, Object 간의 관계는 무엇이며 Java 코드에서 사용될 때 어떻게 매핑됩니까? (0) | 2020.08.13 |
Android 애플리케이션에서 조각을 언제, 왜 사용해야합니까? (0) | 2020.08.13 |
오류 : 'Node'에서 'appendChild'를 실행하지 못했습니다. 매개 변수 1이 'Node'유형이 아닙니다. (0) | 2020.08.13 |