순서가 매겨지지 않은 2개의 리스트(세트 이외)를 효율적으로 비교하려면 어떻게 해야 합니까?
a = [1, 2, 3, 1, 2, 3]
b = [3, 2, 1, 3, 2, 1]
a와 b는 완전히 동일한 요소를 가지며 순서가 다르기 때문에 동등하다고 간주해야 합니다.
실제 리스트는 정수가 아닌 오브젝트(클래스 인스턴스)로 구성됩니다.
O(n): Counter() 메서드가 최선입니다(개체가 해시 가능한 경우).
def compare(s, t):
return Counter(s) == Counter(t)
O(n log n):sorted() 메서드는 다음으로 적합합니다(오더 가능한 오브젝트일 경우).
def compare(s, t):
return sorted(s) == sorted(t)
O(n * n): 객체가 해시 가능하지도 않고 오더 가능하지도 않은 경우 equality를 사용할 수 있습니다.
def compare(s, t):
t = list(t) # make a mutable copy
try:
for elem in s:
t.remove(elem)
except ValueError:
return False
return not t
둘 다 정렬할 수 있습니다.
sorted(a) == sorted(b)
카운트 정렬이 더 효율적일 수도 있습니다(단, 오브젝트가 해시 가능해야 합니다).
>>> from collections import Counter
>>> a = [1, 2, 3, 1, 2, 3]
>>> b = [3, 2, 1, 3, 2, 1]
>>> print (Counter(a) == Counter(b))
True
이 항상 " " " 를할 수 있습니다.Counter()
o O(n) 다 다 다 다 which which which which which which which which
을 항상 수 것을 있는 , 을할 수 .sorted()
Olog n)O(n log n)입니다.
일반적인 경우 정렬할 수 있거나 요소를 가지고 있을 수 없기 때문에 유감스럽게도 O(n^2)인 이와 같은 폴백이 필요합니다.
len(a)==len(b) and all(a.count(i)==b.count(i) for i in a)
테스트에서 이 작업을 수행해야 하는 경우 https://docs.python.org/3.5/library/unittest.html#unittest.TestCase.assertCountEqual
assertCountEqual(first, second, msg=None)
첫 번째 시퀀스는 순서에 관계없이 두 번째와 동일한 요소를 포함합니다.그렇지 않으면 시퀀스 간의 차이를 나열하는 오류 메시지가 생성됩니다.
중복 요소는 첫 번째 요소와 두 번째 요소를 비교할 때 무시되지 않습니다.두 시퀀스에서 각 요소의 카운트가 동일한지 여부를 확인합니다.assertEqual(Counter(list(first)), Counter(list(second))와 동일하지만 캐시할 수 없는 객체의 시퀀스에서도 작동합니다.
버전 3.2의 새로운 기능
또는 2.7의 경우:https://docs.python.org/2.7/library/unittest.html#unittest.TestCase.assertItemsEqual
에서는, ★★★★★★★★★★★★★★★★★★★★★★★★★★★★를 추천합니다.Counter
★★★★★★ 。
가장 좋은 하는 것입니다.Counter
해시할 수 없는 오브젝트에서는 동작하지 않습니다.)이것은 정수의 경우 간단합니다.
sorted(a) == sorted(b)
임의의 오브젝트에서는 조금 더 까다로워집니다.오브젝트 ID(즉, 양쪽 목록에 동일한 오브젝트가 있는지 여부)에 관심이 있는 경우id()
정렬 키로 기능합니다.
sorted(a, key=id) == sorted(b, key==id)
2.x에서는 (Python 2.x, Python 2.x, Python, Python.x, Python.x 에서는 실제로 필요하지 key=
임의의 오브젝트를 임의의 오브젝트와 비교할 수 있기 때문입니다.순서는 임의이지만 안정적이기 때문에 이 목적에서는 정상적으로 동작합니다.오브젝트의 순서는 중요하지 않습니다.단, 순서는 양쪽 리스트에서 동일합니다. Python에서는 여러 상황에서 하는 것은 허용되지 를 들어 정수와 수 없기 오브젝트가 있는 하는 것이 좋습니다.) Python 3은 이 오브젝트의 ID를 명시적으로 사용하는 것이 좋습니다. 예를 들어 문자열을 정수와 비교할 수 없으므로 다양한 유형의 개체가 있을 경우 개체의 ID를 명시적으로 사용하는 것이 좋습니다.)
한편, 리스트의 오브젝트를 값별로 비교하려면 먼저 오브젝트에 대해 "value"가 무엇을 의미하는지 정의해야 합니다.그러면 그것을 키로 제공할 수 있는 방법이 필요합니다(그리고 Python 3의 경우 일관된 유형으로).많은 임의의 오브젝트에 대해 동작할 수 있는 잠재적인 방법 중 하나는 자신의 오브젝트별로 정렬하는 것입니다.repr()
물론, 이것은 많은 시간과 메모리를 낭비할 수 있습니다.repr()
큰 리스트의 문자열 등입니다.
sorted(a, key=repr) == sorted(b, key==repr)
객체가 모두 사용자 고유의 유형인 경우__lt__()
다른 물건과 비교하는 방법을 알 수 있도록 말이죠.그럼 그냥 분류하면 되겠네요.key=
파라미터를 지정합니다.물론, 그 정의도 할 수 있습니다.__hash__()
및 사용Counter
그게 더 빠를 거야
비교가 테스트 컨텍스트에서 수행될 경우 다음을 사용합니다(py>=3.2
( ) 및 ( )2.7<=py<3.2
).
캐시할 수 없는 개체의 시퀀스에서도 작동합니다.
목록에 해시할 수 없는 항목(개체 목록 등)이 포함되어 있는 경우 다음과 같은 카운터 클래스 및 id() 함수를 사용할 수 있습니다.
from collections import Counter
...
if Counter(map(id,a)) == Counter(map(id,b)):
print("Lists a and b contain the same objects")
a, b 리스트로 합니다.
def ass_equal(a,b):
try:
map(lambda x: a.pop(a.index(x)), b) # try to remove all the elements of b from a, on fail, throw exception
if len(a) == 0: # if a is empty, means that b has removed them all
return True
except:
return False # b failed to remove some items from a
해시 가능 상태로 만들거나 정렬할 필요가 없습니다.
당신의 경우 아래 코드 조각이 효과가 있기를 바랍니다.
if ((len(a) == len(b)) and
(all(i in a for i in b))):
print 'True'
else:
print 'False'
이렇게 하면 양쪽 목록의 모든 요소가a
&b
순서와 관계없이 동일합니다.
자세한 내용은 이 질문의 답변을 참조하십시오.
목록을 비교하는 함수를 직접 작성할 수 있습니다.
두 개의 목록을 얻읍시다.
list_1=['John', 'Doe']
list_2=['Doe','Joe']
먼저 빈 사전을 정의하고 목록 항목을 세어 사전에 씁니다.
def count_list(list_items):
empty_dict={}
for list_item in list_items:
list_item=list_item.strip()
if list_item not in empty_dict:
empty_dict[list_item]=1
else:
empty_dict[list_item]+=1
return empty_dict
그 후 다음 기능을 사용하여 두 목록을 비교합니다.
def compare_list(list_1, list_2):
if count_list(list_1)==count_list(list_2):
return True
return False
compare_list(list_1,list_2)
from collections import defaultdict
def _list_eq(a: list, b: list) -> bool:
if len(a) != len(b):
return False
b_set = set(b)
a_map = defaultdict(lambda: 0)
b_map = defaultdict(lambda: 0)
for item1, item2 in zip(a, b):
if item1 not in b_set:
return False
a_map[item1] += 1
b_map[item2] += 1
return a_map == b_map
데이터가 정렬되지 않은 경우 정렬이 매우 느릴 수 있습니다(항목의 순서가 일정 수준일 경우 시간 정렬이 특히 좋습니다.또한 둘 다 정렬하려면 두 목록을 모두 완전히 반복해야 합니다.
목록을 변환하는 것이 아니라 세트를 할당하고 왼쪽 멤버십 체크를 수행합니다.그 동안 각 항목이 몇 개 존재하는지 카운트합니다.
- 두 목록의 길이가 동일하지 않은 경우 단락했다가 반환할 수 있습니다.
False
지금 당장. - 내의 했을 경우
a
것b
할 수 있다False
- 을 다 '비교할 수치다'의 할 수 .
a_map
★★★★★★★★★★★★★★★★★」b_map
이치노
이것에 의해, 많은 경우, 양쪽의 리스트를 반복하기 전에 단락할 수 있습니다.
플러그 인:
def lists_equal(l1: list, l2: list) -> bool:
"""
import collections
compare = lambda x, y: collections.Counter(x) == collections.Counter(y)
ref:
- https://stackoverflow.com/questions/9623114/check-if-two-unordered-lists-are-equal
- https://stackoverflow.com/questions/7828867/how-to-efficiently-compare-two-unordered-lists-not-sets
"""
compare = lambda x, y: collections.Counter(x) == collections.Counter(y)
set_comp = set(l1) == set(l2) # removes duplicates, so returns true when not sometimes :(
multiset_comp = compare(l1, l2) # approximates multiset
return set_comp and multiset_comp #set_comp is gere in case the compare function doesn't work
언급URL : https://stackoverflow.com/questions/7828867/how-to-efficiently-compare-two-unordered-lists-not-sets
'programing' 카테고리의 다른 글
Vuex 저장소의 NuxTJS 값이 정의되지 않았습니다. (0) | 2022.09.08 |
---|---|
JAVA_의 설정 방법Linux의 HOME은 모든 사용자를 대상으로 합니다. (0) | 2022.09.08 |
Php가 최신 업데이트된 sql 프로시저 결과를 반환하지 않음 (0) | 2022.09.08 |
교리 쿼리에서 null 값을 필터로 지정하는 방법은 무엇입니까? (0) | 2022.09.08 |
어떻게 CentOS7에 MySQL루트 계정 비밀 번호를 바꾸도록? (0) | 2022.09.08 |