Python: Перевірте, чи один набір повністю містить інший?


86

Чи є швидкий спосіб перевірити, чи один комплект повністю містить інший?

Щось на зразок:

>>>[1, 2, 3].containsAll([2, 1])
True

>>>[1, 2, 3].containsAll([3, 5, 9])
False

Відповіді:


131

Це списки, але якщо ви дійсно маєте на увазі набори, ви можете використовувати метод issubset.

>>> s = set([1,2,3])
>>> t = set([1,2])
>>> t.issubset(s)
True
>>> s.issuperset(t)
True

Для списку ви не зможете зробити краще, ніж перевірити кожен елемент.


3
Я бачу дивне відчуття дежаву, коли бачу цю відповідь
Крістоф Руссі,

ви повинні знати про семантику issubset()неcontains()
wikier

37

Для повноти: це еквівалентно issubset(хоча, можливо, трохи менше явного / читабельного):

>>> set([1,2,3]) >= set([2,1])
True
>>> set([1,2,3]) >= set([3,5,9])
False

Проблема полягає в a = set ([]) і b = set (['a', 'b']), тоді a.issubset (b) - True
darkman

4

Один варіант залишається недоторканим - віднімання:

>>> {1, 2} - {1, 2, 3}
set([])
>>> {1, 2, 3} - {1, 2}
set([3])

В основному ви перевіряєте, які елементи у першому списку відсутні у другому списку.

Я знайшов це дуже зручним, оскільки ви могли показати, яких значень не вистачає:

>>> def check_contains(a, b):
...     diff = a - b
...     if not diff:
...         # All elements from a are present in b
...         return True
...     print('Some elements are missing: {}'.format(diff))
...     return False
...
>>> check_contains({1, 2}, {1, 2, 3})
True
>>> check_contains({1, 2, 3}, {1, 2})
Some elements are missing: set([3])
False

4

Ви можете використовувати set.issubset()або set.issuperset()(або їх аналоги на основі оператора: <=і >=). Зверніть увагу, що методи прийматимуть як аргумент будь-який ітерабель , а не лише набір:

>>> {1, 2}.issubset([1, 2, 3])
True
>>> {1, 2, 3}.issuperset([1, 2])
True

Однак, якщо ви використовуєте оператори, обидва аргументи мають бути наборами:

>>> {1, 2} <= {1, 2, 3}
True
>>> {1, 2, 3} >= {1, 2}
True

4

Якщо ви підозрюєте, що набір є підмножиною іншого, і перетинаєте ці два набори разом, результат дорівнює самому собі, якщо це підмножина.

a = [2,1,3,3]
b = [5,4,3,2,1]
set(a).intersection(set(b)) == set(a)
>>True

1
Нехай A = set(a)і B = set(b)за осудність. Тоді це порівняння ефективно зводиться до len(A.intersection(B)) == len(A). Тобто не потрібно порівнювати самі набори ; потрібно порівнювати лише потужність цих наборів. Навіть цієї оптимізації, мабуть, недостатньо, щоб зробити цей підхід кращим. Значно більш читабельним і ефективним issubset()і <=підходи майже напевно , що всі хочуть.
Сесіл Каррі

@CecilCurry Правда - я неправильно вжив слово "потужність", оскільки це вимірювання довжини. Я оновив формулювання. Ваша оптимізація - це помилка на основі моєї помилки. Не оптимізація. Буквальне формулювання "intersection ()" читається явніше, ніж перевантажені наслідки "> =", а твердження, що "issubset ()" легше читати, є свого роду усуненням очевидного, оскільки це найпопулярніша відповідь. Не соромтеся внести творче рішення, крім повторення відповідей інших.
Джордан Стефанеллі

1
>>> set([1,2,3]).issuperset(set([2,1]))
True 
>>>    
>>> set([1,2,3]).issuperset(set([3,5,9]))
False

3
Подумайте, як правильно відформатувати відповідь та додати якесь пояснення.
Сем

0

Нижче функція повертає 0, якщо основний список не містить підспису повністю і 1, якщо містить повністю.

def islistsubset(sublist,mainlist):
     for item in sublist:
             if item in mainlist:
                     contains = 1
             else:
                     contains = 0
                     break;
     return contains

1
Це O (n ^ 2) під час використання набору операцій, оскільки в деяких з існуючих відповідей набагато швидше. Це також можна написати просто any(item in mainlist for item in sublist).
Ігуанановт

Погодьтеся, я міг би також написати def islistsubset (підсписок, основний список): містить = 1 для елемента в підсписку: якщо елемент у основному списку: продовжити ще: містить = 0 перерва; return містить Отже лише 2 завдання на дзвінок
Бобін Мотті Томас

@BobinMottiThomas Ви можете просто повернути True або False, не створюючи жодної тимчасової змінної. для товару в list_a: якщо елемента немає в list_b: return False return True
Йорданія Стефанеллі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.