Как проверить, есть ли один из следующих пунктов в списке? - PullRequest
186 голосов
/ 11 апреля 2009

Я пытаюсь найти краткий путь, чтобы увидеть, есть ли какой-либо из следующих пунктов в списке, но моя первая попытка не работает. Помимо написания функции для этого, есть любой короткий способ проверить, есть ли один из нескольких элементов в списке.

>>> a = [2,3,4]
>>> print (1 or 2) in a
False
>>> print (2 or 1) in a
True

Ответы [ 14 ]

223 голосов
/ 11 апреля 2009
>>> L1 = [2,3,4]
>>> L2 = [1,2]
>>> [i for i in L1 if i in L2]
[2]


>>> S1 = set(L1)
>>> S2 = set(L2)
>>> S1.intersection(S2)
set([2])

И пустые списки, и пустые наборы имеют значение False, поэтому вы можете использовать это значение как истинное значение.

183 голосов
/ 11 апреля 2009

Ах, Тобиас, ты избил меня до этого. Я думал об этом небольшом изменении вашего решения:

>>> a = [1,2,3,4]
>>> b = [2,7]
>>> print(any(x in a for x in b))
True
26 голосов
/ 11 апреля 2009

Может быть, немного более ленивый:

a = [1,2,3,4]
b = [2,7]

print any((True for x in a if x in b))
16 голосов
/ 11 апреля 2009

Подумайте, что на самом деле говорит код!

>>> (1 or 2)
1
>>> (2 or 1)
2

Это, вероятно, должно объяснить это. :) По-видимому, Python реализует «ленивый или», что неудивительно. Он выполняет это примерно так:

def or(x, y):
    if x: return x
    if y: return y
    return False

В первом примере x == 1 и y == 2. Во втором примере все наоборот. Вот почему он возвращает разные значения в зависимости от их порядка.

13 голосов
/ 27 марта 2014
a = {2,3,4}
if {1,2} & a:
    pass

Код гольф версии. Подумайте об использовании набора, если это имеет смысл. Я считаю это более читабельным, чем понимание списка.

12 голосов
/ 25 июня 2014

1 строка без списочных пониманий.

>>> any(map(lambda each: each in [2,3,4], [1,2]))
True
>>> any(map(lambda each: each in [2,3,4], [1,5]))
False
>>> any(map(lambda each: each in [2,3,4], [2,4]))
True
6 голосов
/ 11 апреля 2009

Лучшее, что я мог придумать:

any([True for e in (1, 2) if e in a])
4 голосов
/ 05 сентября 2018

В python 3 мы можем начать использовать распакованную звездочку. Дано два списка:

any({*a} & {*b})
4 голосов
/ 21 января 2014

Когда вы думаете «проверить, если a в b», подумайте о хешах (в данном случае, устанавливает). Самый быстрый способ - хэшировать список, который вы хотите проверить, а затем проверять каждый элемент в нем.

Вот почему Джо Коберг отвечает быстро: проверка пересечения множества очень быстрая.

Когда у вас мало данных, создание наборов может быть пустой тратой времени. Итак, вы можете составить список и просто проверить каждый элемент:

tocheck = [1,2] # items to check
a = [2,3,4] # the list

a = set(a) # convert to set (O(len(a)))
print [i for i in tocheck if i in a] # check items (O(len(tocheck)))

Когда количество предметов, которые вы хотите проверить, мало, разница может быть незначительной. Но сравните множество чисел с большим списком ...

Тесты:

from timeit import timeit

methods = ['''tocheck = [1,2] # items to check
a = [2,3,4] # the list
a = set(a) # convert to set (O(n))
[i for i in tocheck if i in a] # check items (O(m))''',

'''L1 = [2,3,4]
L2 = [1,2]
[i for i in L1 if i in L2]''',

'''S1 = set([2,3,4])
S2 = set([1,2])
S1.intersection(S2)''',

'''a = [1,2]
b = [2,3,4]
any(x in a for x in b)''']

for method in methods:
    print timeit(method, number=10000)

print

methods = ['''tocheck = range(200,300) # items to check
a = range(2, 10000) # the list
a = set(a) # convert to set (O(n))
[i for i in tocheck if i in a] # check items (O(m))''',

'''L1 = range(2, 10000)
L2 = range(200,300)
[i for i in L1 if i in L2]''',

'''S1 = set(range(2, 10000))
S2 = set(range(200,300))
S1.intersection(S2)''',

'''a = range(200,300)
b = range(2, 10000)
any(x in a for x in b)''']

for method in methods:
    print timeit(method, number=1000)

Скорость:

M1: 0.0170331001282 # make one set
M2: 0.0164539813995 # list comprehension
M3: 0.0286040306091 # set intersection
M4: 0.0305438041687 # any

M1: 0.49850320816 # make one set
M2: 25.2735087872 # list comprehension
M3: 0.466138124466 # set intersection
M4: 0.668627977371 # any

Метод, который является достаточно быстрым, состоит в том, чтобы сделать один набор (из списка), но пересечение работает с большими наборами данных лучше всего!

3 голосов
/ 11 апреля 2009

В некоторых случаях (например, уникальные элементы списка) могут использоваться операции над множествами.

>>> a=[2,3,4]
>>> set(a) - set([2,3]) != set(a)
True
>>> 

Или, используя set.isdisjoint () ,

>>> not set(a).isdisjoint(set([2,3]))
True
>>> not set(a).isdisjoint(set([5,6]))
False
>>> 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...