2013-05-29 2 views
3

Что было бы самым эффективным способом (с точки зрения памяти и процессора) для извлечения элементов из большого списка в Python? Это хороший способ?Эффективный выбор списка

a = range(0,100000) 
a[:] = [item for item in a if item > 10] 

Цифры здесь всего лишь пример. Также могут быть:

a = ["my", "very", "big", "list"] 
a[:] = [item for item in a if item.startswith("b")] 
+2

ваш список не будет всегда заказывать правильно? – jamylak

+2

Здесь будет неплохо. – Blender

+2

Вы имеете в виду 'если item> 10' – ajon

ответ

2

Если вы действительно хотите получить список (и вы хотите заменить свой первоначальный список на месте), вы, вероятно, не будет делать гораздо лучше, чем то, что у вас есть чистый питон. Однако это часто не требуется. Часто вы просто хотите Iterable объект:

generator = (item for item in a if item > 10) 
for item in generator: 
    ... 

Это будет меньше памяти и производительность должна быть примерно такой же.

+0

Какова будет эффективность? Элементы все равно хранятся в памяти. – RickyA

+0

@ RickyA - когда вы выполняете назначение среза, сначала оценивается правая сторона. если вы отфильтровываете только несколько элементов, то вы в основном сохраняете свой список в памяти дважды (прежде чем назначать обратно в исходный список). Это, как правило, не имеет большого значения, но вы спрашивали об эффективности памяти ... Что касается производительности, вам нужно будет «timeit», но я бы ожидал, что оба подхода будут поровну. – mgilson

+0

ОК, но накладные расходы будут только новым списком со ссылками на значения. Не копия фактических значений, поскольку понимание списка не копирует значения. Правильно? – RickyA

1

Python имеет функции генератора, специально созданные для этой цели. См. Документы here. Помимо использования range (в документах предлагается использовать xrange, который возвращает генератор), ваша реализация прекрасна.

Документы имеют следующий пример:

# Build and return a list 
def firstn(n): 
    num, nums = 0, [] 
    while num < n: 
     nums.append(num) 
     num += 1 
    return nums 

sum_of_first_n = sum(firstn(1000000)) 

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

# Using the generator pattern (an iterable) 
class firstn(object): 
    def __init__(self, n): 
     self.n = n 
     self.num, self.nums = 0, [] 

    def __iter__(self): 
     return self 

    def next(self): 
     if self.num < self.n: 
      cur, self.num = self.num, self.num+1 
      return cur 
     else: 
      raise StopIteration() 

sum_of_first_n = sum(firstn(1000000)) 
+0

Не могли бы вы привести пример – jamylak

+1

'xrange' не является генератором, это объект последовательности, который оценивает лениво – jamylak

+0

Кажется, вы правы, но я был смущен, потому что ссылка имеет это:« Оба диапазона и xrange представляют диапазон числа и имеют одну и ту же сигнатуру функции, но диапазон возвращает список, а xrange возвращает генератор (по крайней мере, в концепции, реализация может отличаться). " – isaach1000

0

Вы можете использовать filter или generators здесь

генератор

>>> data = [10, 20, 4, 4, 11, 13.4] 
>>> custom_filter = (i for i in data if i > 10) 
>>> [j for j in custom_filter] 
[20, 11, 13.4] 
>>> 

фильтр

>>> data = [10, 20, 4, 4, 11, 13.4] 
>>> custom_filter = filter(lambda x: x > 10, data) 
>>> custom_filter 
[20, 11, 13.4] 
>>> 
Смежные вопросы