метод быстрого фильтра в python - PullRequest
0 голосов
/ 14 октября 2008

Я хочу отфильтровать два списка любым быстрым способом в скрипте Python. Для этой цели я использовал встроенный метод filter(). но это довольно медленно и занимает слишком много времени, потому что у меня очень большой список, я думаю, более 5 миллионов пунктов в каждом списке или может быть больше Я не знаю, как я это сделаю. Пожалуйста, если у кого-нибудь есть идея или напишите небольшую функцию для нее.

Ответы [ 6 ]

14 голосов
/ 14 октября 2008

Возможно, ваши списки слишком велики и не помещаются в памяти, и вы испытываете избиение . Если источники находятся в файлах, вам не нужен весь список в памяти сразу. Попробуйте использовать itertools , например ::

from itertools import ifilter

def is_important(s):
   return len(s)>10

filtered_list = ifilter(is_important, open('mylist.txt'))

Обратите внимание, что ifilter возвращает итератор , который быстр и экономит память.

Трюки с генераторами - это учебное пособие Дэвида М. Бизли, в котором рассказывается о некоторых интересных применениях генераторов .

4 голосов
/ 14 октября 2008

Если вы вообще можете избежать создания списков, вы будете счастливее.

Вместо

aBigList = someListMakingFunction()
filter( lambda x:x>10, aBigList )

Возможно, вы захотите взглянуть на свою функцию, которая составляет список.

def someListMakingGenerator( ):
    for x in some source:
        yield x

Тогда ваш фильтр не задействует гигантский тракт памяти

def myFilter( aGenerator ):
    for x in aGenerator:
        if x > 10: 
            yield x

Используя генераторы, вы мало что храните в памяти.

2 голосов
/ 14 октября 2008

Фильтр создаст новый список, поэтому, если ваш оригинал очень большой, вы можете использовать в два раза больше памяти. Если вам нужно только обрабатывать результаты итеративно, а не использовать его в качестве реального списка произвольного доступа, вам, вероятно, лучше использовать вместо этого. то есть.

for x in itertools.ifilter(condition_func, my_really_big_list):
    do_something_with(x)

Другими советами по скорости является использование встроенной функции Python, а не функции, которую вы пишете сами. Там есть itertools.ifilterfalse специально для случай, когда в противном случае вам нужно будет ввести лямбду, чтобы аннулировать ваш чек. (например, «ifilter (lambda x: not x.isalpha (), l)» следует написать «ifilterfalse (str.isalpha, l)»)

2 голосов
/ 14 октября 2008

Я полагаю, что filter () работает настолько быстро, насколько это возможно, без необходимости кодировать функцию фильтрации в C (и в этом случае лучше кодировать весь процесс фильтрации в C).

Почему бы вам не вставить функцию, по которой вы фильтруете? Это может привести к более легкой оптимизации.

Читайте это об оптимизации в Python. И это об API Python / C.

1 голос
/ 14 октября 2008

Может быть полезно знать, что обычно понимание условного списка намного быстрее, чем соответствующая лямбда:

>>> import timeit
>>> timeit.Timer('[x for x in xrange(10) if (x**2 % 4) == 1]').timeit()
2.0544309616088867
>>> timeit.f = lambda x: (x**2 % 4) == 1
timeit.Timer('[x for x in xrange(10) if f(x)]').timeit()
>>> 
3.4280929565429688

(Не уверен, почему мне нужно было поместить f в пространство имен timeit. Там модуль не особо использовался.)

1 голос
/ 14 октября 2008

Прежде чем сделать это в C, вы можете попробовать numpy . Возможно, вы можете превратить свою фильтрацию в сокращение чисел.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...