Як перевірити, чи всі перелічені нижче елементи є у списку?


113

Я виявив, що існує пов'язане запитання про те, як знайти, чи принаймні один елемент у списку:
Як перевірити, чи є один із наведених нижче пунктів у списку?

Але який найкращий і пітонічний спосіб з’ясувати, чи всі предмети існують у списку?

Шукаючи через документи, я знайшов таке рішення:

>>> l = ['a', 'b', 'c']
>>> set(['a', 'b']) <= set(l)
True
>>> set(['a', 'x']) <= set(l)
False

Іншим рішенням буде таке:

>>> l = ['a', 'b', 'c']
>>> all(x in l for x in ['a', 'b'])
True
>>> all(x in l for x in ['a', 'x'])
False

Але тут потрібно зробити більше набору тексту.

Чи є інші рішення?


5
Що не так set(smaller) <= set(larger)?
eumiro

1
Я думаю, що ваше друге рішення з "всім" для мене виглядає просто чудово і пітонічно.
Джіхо Нох

Відповіді:


156

Оператори, як <=у Python, як правило, не змінюються, щоб означати щось значно інше, ніж "менше або рівне". Це незвично, як це робить стандартна бібліотека - це пахне як застарілий API для мене.

Використовуйте еквівалент і чіткіше з ім'ям методу set.issubset. Зауважте, що вам не потрібно перетворювати аргумент у набір; це зробить це для вас, якщо потрібно.

set(['a', 'b']).issubset(['a', 'b', 'c'])

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

1
Хоча я згоден з настроями, я досить гаразд з ідеєю <=і issubsetсенсом того самого. Чому це вам не подобається?
Кірк Штраузер

2
@Just: Перш за все, тому що не очевидно, що <=означає набір, не шукаючи його в документах або попередньо знаючи, що це означає в теорії множин, тоді як усі знають, що issubsetозначає автоматично.
Гленн Мейнард

2
Ви знаєте математичний оператор для (не належного) підмножини? це в основному схоже на округлене <=;)
dom0

люблю це рішення. чи є спосіб отримати місце розташування індексу або значення списку замість bool (правда: помилково)?
Влад Гулін

62

Я, ймовірно, використовував setби такий спосіб:

set(l).issuperset(set(['a','b'])) 

або навпаки:

set(['a','b']).issubset(set(l)) 

Я вважаю це трохи читабельніше, але це може бути надмірне вбивство. Набори особливо корисні для обчислення об'єднання / перетину / відмінностей між колекціями, але це може бути не найкращим варіантом у цій ситуації ...


Власне, MySet.issubset(MyOtherSet)і MySet <= MyOtherSetте саме.
Вок

1
@wok: О, я цього не знав, але думаю, що синтаксис <= трохи заплутаний, оскільки подібний синтаксис можна використовувати зі списками, але з зовсім іншим значенням.
Цимбаляр

3
насправді це не так заплутано, якщо згадати, що включення визначає частковий порядок для будь-якого набору. Насправді дещо заплутаний той <=сенс, який він має для послідовностей: можна очікувати, що це означає «це сукупність», а не лексикографічне впорядкування.
aaronasterling

1
@aaronasterling: ммм, я особисто не думаю занадто багато про "частковий порядок", коли набираю код :-), але я згоден на те, що використання <=з послідовностями теж якось дивно ...
tsimbalar

3
Я побіг в маленьку Gotcha тут я хотів би згадати: Якщо ви використовуєте цей метод, ви є перетворення списків в набори, що не означають дублікатів. set(['a','a']).issubset(['a'])повертає True.
Апельсин

11

Мені подобаються ці два, тому що вони здаються найбільш логічними, останні коротші та, ймовірно, найшвидші (показано тут, використовуючи setбуквальний синтаксис, який був підтриманий на Python 2.7):

all(x in {'a', 'b', 'c'} for x in ['a', 'b'])
#   or
{'a', 'b'}.issubset({'a', 'b', 'c'})

Рішення "все" є найшвидшим, коли ви вимірюєте його timeit (). Це має бути прийнятою відповіддю.
Аттерссон

3

Що робити, якщо ваші списки містять такі дублікати:

v1 = ['s', 'h', 'e', 'e', 'p']
v2 = ['s', 's', 'h']

Набори не містять дублікатів. Отже, наступний рядок повертає True.

set(v2).issubset(v1)

Для підрахунку дублікатів можна використовувати код:

v1 = sorted(v1)
v2 = sorted(v2)


def is_subseq(v2, v1):
    """Check whether v2 is a subsequence of v1."""
    it = iter(v1)
    return all(c in it for c in v2) 

Отже, наступний рядок повертає False.

is_subseq(v2, v1)

1

Це те, що я шукав в Інтернеті, але, на жаль, не знайшов в Інтернеті, але під час експерименту над інтерпретатором python.

>>> case  = "caseCamel"
>>> label = "Case Camel"
>>> list  = ["apple", "banana"]
>>>
>>> (case or label) in list
False
>>> list = ["apple", "caseCamel"]
>>> (case or label) in list
True
>>> (case and label) in list
False
>>> list = ["case", "caseCamel", "Case Camel"]
>>> (case and label) in list
True
>>>

і якщо у вас є довгий список змінних, розміщених у a sublist variable

>>>
>>> list  = ["case", "caseCamel", "Case Camel"]
>>> label = "Case Camel"
>>> case  = "caseCamel"
>>>
>>> sublist = ["unique banana", "very unique banana"]
>>>
>>> # example for if any (at least one) item contained in superset (or statement)
...
>>> next((True for item in sublist if next((True for x in list if x == item), False)), False)
False
>>>
>>> sublist[0] = label
>>>
>>> next((True for item in sublist if next((True for x in list if x == item), False)), False)
True
>>>
>>> # example for whether a subset (all items) contained in superset (and statement)
...
>>> # a bit of demorgan's law
...
>>> next((False for item in sublist if item not in list), True)
False
>>>
>>> sublist[1] = case
>>>
>>> next((False for item in sublist if item not in list), True)
True
>>>
>>> next((True for item in sublist if next((True for x in list if x == item), False)), False)
True
>>>
>>>

0

Прикладом того, як це зробити за допомогою лямбда-виразу, може бути:

issublist = lambda x, y: 0 in [_ in x for _ in y]

1
Будь ласка, додайте коментарі, щоб пояснити / уточнити свою відповідь
Шарад

0

Не справа ОП, але - для тих, хто хоче стверджувати перехрестя в диктатах і потрапив сюди через погану гугла (наприклад, я) - вам потрібно працювати dict.items:

>>> a = {'key': 'value'}
>>> b = {'key': 'value', 'extra_key': 'extra_value'}
>>> all(item in a.items() for item in b.items())
True
>>> all(item in b.items() for item in a.items())
False

Це тому, що dict.itemsповертаються кортежі пар ключів / значень, і так само, як і будь-який об'єкт в Python, вони взаємозамінно порівнянні

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.