Как отфильтровать список на основе элементов в другом списке в python

#python #list #filter

#python #Список #Фильтр

Вопрос:

У меня есть список A, содержащий около 62 000 чисел, и другой список B, содержащий около 370 000. Я хотел бы отфильтровать B так, чтобы он содержал только элементы из A. Я пробовал что-то вроде этого:

 A=[0,3,5,73,88,43,2,1]
B=[0,5,10,42,43,56,83,88,892,1089,3165]
C=[item for item in A if item in set(B)] 
  

Который работает, но, очевидно, очень медленно для таких больших списков, потому что (я думаю?) Поиск продолжается по всему B, даже если элемент уже найден в B. Итак, скрипт просматривает список из 370 000 элементов 62 000 раз.

Элементы в A и B уникальны (B содержит список уникальных значений от 0 до 700 000, а A содержит уникальное подмножество из них), поэтому, как только A [i] найден в B, поиск может прекратиться. Значения также приведены в порядке возрастания, если это что-то значит.

Есть ли какой-нибудь способ сделать это быстрее?

Ответ №1:

Это создает новый set(B) для каждого элемента в A. Вместо этого используйте встроенный set.intersection :

 C = set(A).intersection(B)
  

Комментарии:

1. Приятно! 1. Как насчет set(a) amp; set(B) ? Просто кажется немного чище.

2. @ChristianDean Для этого требуется создать третий набор, set(B) . В приведенном выше примере только set(A) и C создаются как новые объекты, B просто повторяются.

3. Это чрезвычайно быстро (и бонусные баллы за простоту). Именно то, что я искал. Спасибо.

Ответ №2:

Чтобы быть действительно уверенным, что я сделал как можно быстрее, я бы сделал это :

 A=[0,3,5,73,88,43,2,1]
B=[0,5,10,42,43,56,83,88,892,1089,3165]

B_filter = B.copy()
C = []
for item in A:
    if filter in B_filter:
        C.append(item)
        B_filter.pop(0) # B_filter is a list, and it's in ascending order so always the first
  

Если вас не волнует потеря вашего B списка, вы можете просто использовать B вместо B_filter и не объявлять B_filter , поэтому вам не нужно копировать список размером 370 кб.