2013-06-27 2 views
0

У меня есть большой список предметов (а в списке иногда может храниться 1 миллион предметов). Теперь я хочу фильтровать элементы в этом списке в зависимости от длины каждого элемента. т. е. я хочу добавить элементы, которые имеют либо меньше 7 символов, либо больше 24 символов. Код, который я написал это:выберите элементы из списка, основанные на длине позиции

returnNumbers //the list that holds million items 
for num in returnNumbers: 
    if((len(num)<7 or len(num)>24)): 
     invalidLengthNumbers.append(num); 

Не уверен, что, если есть лучший способ сделать это, как идти через 1 миллиона единиц время принятия.

ответ

3

Вы хотите принять итеративный подход, действительно.

Ваш код может быть заменен списком понимания:

invalidLengthNumbers = [num for num in returnNumbers if len(num) < 7 or len(num) > 24] 

или, короче, и только принимая один len() вызов, воспользовавшись сравнения цепочки:

invalidLengthNumbers = [num for num in returnNumbers if not 7 <= len(num) <= 24] 

, но это будет только немного быстрее.

Если вам нужно зациклиться на invalidLengthNumbers позже, не используйте список посредников. Петля и фильтр за returnNumbers напрямую. Возможно, даже returnNumbers сам может быть заменен генератором, и фильтрация этого генератора может быть выполнена итеративно.

def produceReturnNumbers(): 
    for somevalue in someprocess: 
     yield some_other_value_based_on_somevalue 

from itertools import ifilter 

for invalid in ifilter(lambda n: not 7 <= len(n) <= 24, produceReturnNumbers()): 
    # do something with invalid 

Теперь у вас больше нет списка из 1 миллиона предметов. У вас есть генератор, который будет производить 1 миллион предметов по мере необходимости, не удерживая все это в памяти.

+1

+1. Кстати, отрицание 'if len (num) <7 или len (num)> 24' будет' если не 7 <= len (num) <= 24'. Я считаю, что немного читаем ... – mata

+0

@mata: действительно; отрицание дает нам возможность цепочки и только вызов 'len()' один раз. Благодарю. –