#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 кб.