Проверьте, равны ли два неупорядоченных списка
Я ищу простой (и быстрый) способ определить, содержат ли два неупорядоченных списка те же элементы:
Например:
['one', 'two', 'three'] == ['one', 'two', 'three'] : true
['one', 'two', 'three'] == ['one', 'three', 'two'] : true
['one', 'two', 'three'] == ['one', 'two', 'three', 'three'] : false
['one', 'two', 'three'] == ['one', 'two', 'three', 'four'] : false
['one', 'two', 'three'] == ['one', 'two', 'four'] : false
['one', 'two', 'three'] == ['one'] : false
Я надеюсь сделать это без использования карты.
Ответы
Ответ 1
Python имеет встроенный тип данных для неупорядоченного набора (хешируемых) вещей, называемого set
. Если вы конвертируете оба списка в наборы, сравнение будет неупорядоченным.
set(x) == set(y)
Документация на set
EDIT: @mdwhatcott указывает, что вы хотите проверить наличие дубликатов. set
игнорирует их, поэтому вам нужна аналогичная структура данных, которая также отслеживает количество элементов в каждом списке. Это называется multiset; наилучшим приближением в стандартной библиотеке является collections.Counter
:
>>> import collections
>>> compare = lambda x, y: collections.Counter(x) == collections.Counter(y)
>>>
>>> compare([1,2,3], [1,2,3,3])
False
>>> compare([1,2,3], [1,2,3])
True
>>> compare([1,2,3,3], [1,2,2,3])
False
>>>
Ответ 2
Если элементы всегда сортируются по порядку, как в вашем примере, то встроенная .sort()
(timsort) должна быть быстрой:
>>> a = [1,1,2]
>>> b = [1,2,2]
>>> a.sort()
>>> b.sort()
>>> a == b
False
Если вы не хотите сортировать inplace, вы можете использовать sorted()
.
На практике это всегда будет быстрее, чем collections.Counter()
(несмотря на асимптотически O(n)
время лучше, чем O(n*log(n))
для .sort()
). Измерьте это; Если это важно.
Ответ 3
sorted(x) == sorted(y)
Копирование здесь: Проверьте, равны ли два неупорядоченных списка
Я думаю, что это лучший ответ на этот вопрос, потому что
- Это лучше, чем использование счетчика, как указано в этом ответе
- x.sort() сортирует x, что является побочным эффектом. sorted (x) возвращает новый список.
Ответ 4
Вы хотите увидеть, содержат ли они одни и те же элементы, но не заботятся о порядке.
Вы можете использовать набор:
>>> set(['one', 'two', 'three']) == set(['two', 'one', 'three'])
True
Но сам объект set будет содержать только один экземпляр каждого уникального значения и не сохранит порядок.
>>> set(['one', 'one', 'one']) == set(['one'])
True
Итак, если отслеживание дубликатов/длина важна, вы, вероятно, захотите также проверить длину:
def are_eq(a, b):
return set(a) == set(b) and len(a) == len(b)
Ответ 5
если вы не хотите использовать библиотеку коллекций, вы всегда можете сделать что-то вроде этого:
что a
и b
являются вашими списками, следующее возвращает количество соответствующих элементов (он рассматривает порядок).
sum([1 for i,j in zip(a,b) if i==j])
Следовательно,
len(a)==len(b) and len(a)==sum([1 for i,j in zip(a,b) if i==j])
будет True
, если оба списка совпадают, содержат одни и те же элементы и в том же порядке. False
в противном случае.
Итак, вы можете определить функцию сравнения, такую как первый ответ выше, но без библиотеки коллекций.
compare = lambda a,b: len(a)==len(b) and len(a)==sum([1 for i,j in zip(a,b) if i==j])
и
>>> compare([1,2,3], [1,2,3,3])
False
>>> compare([1,2,3], [1,2,3])
True
>>> compare([1,2,3], [1,2,4])
False
Ответ 6
Ответ одного лайнера на вышеупомянутый вопрос: -
пусть два списка будут list1 и list2,
и ваше требование состоит в том, чтобы убедиться, что в двух списках есть одни и те же элементы, тогда, как и я, следующий подход будет наилучшим: -
if ((len(list1) == len(list2)) and
(all(i in list2 for i in list1))):
print 'True'
else:
print 'False'
Вышеупомянутый фрагмент кода будет работать в соответствии с вашими потребностями, то есть все ли элементы списка1 находятся в списке2 и наоборот.
Но если вы хотите просто проверить, присутствуют ли все элементы list1 в списке2 или нет, тогда вам нужно использовать только следующую часть кода: -
if all(i in list2 for i in list1):
print 'True'
else:
print 'False'
Разница в том, что позже будет напечатан True, если в списке2 есть дополнительные элементы вместе со всеми элементами списка1. Простыми словами, он гарантирует, что все элементы списка1 должны присутствовать в списке2, независимо от того, есть ли в списке2 некоторые дополнительные элементы или нет.
Ответ 7
Предполагая, что вы уже знаете, что списки имеют одинаковый размер, следующее гарантирует True, если и только если два вектора абсолютно одинаковы (включая порядок)
functools.reduce(lambda b1,b2: b1 and b2, map(lambda e1,e2: e1==e2, listA, ListB), True)
Пример:
>>> from functools import reduce
>>> def compvecs(a,b):
... return reduce(lambda b1,b2: b1 and b2, map(lambda e1,e2: e1==e2, a, b), True)
...
>>> compvecs(a=[1,2,3,4], b=[1,2,4,3])
False
>>> compvecs(a=[1,2,3,4], b=[1,2,3,4])
True
>>> compvecs(a=[1,2,3,4], b=[1,2,4,3])
False
>>> compare_vectors(a=[1,2,3,4], b=[1,2,2,4])
False
>>>
Ответ 8
Как получить строковое представление списков и их сравнение?
>>> l1 = ['one', 'two', 'three']
>>> l2 = ['one', 'two', 'three']
>>> l3 = ['one', 'three', 'two']
>>> print str(l1) == str(l2)
True
>>> print str(l1) == str(l3)
False