Как получить n следующих значений генератора в списке (python) - PullRequest
38 голосов
/ 11 ноября 2010

Я сделал генератор для чтения файла слово за словом, и он прекрасно работает.

def word_reader(file):
    for line in open(file):
        for p in line.split():
            yield p

reader = word_reader('txtfile')
next(reader)

Какой самый простой способ получить n следующих значений в списке?

Ответы [ 5 ]

49 голосов
/ 11 ноября 2010

Использование itertools.islice:

list(itertools.islice(it, n))
11 голосов
/ 11 ноября 2010

РЕДАКТИРОВАТЬ : Используйте itertools.islice.Приведенный ниже шаблон, предложенный мною, является плохой идеей - он падает, когда it дает менее n значений, и это поведение зависит от тонких проблем, поэтому люди, читающие такой код, вряд ли поймут его точную семантику.

Существует также

[next(it) for _ in range(n)]

, который может (?) Быть более понятным для людей, не знакомых с itertools;но если вы много работаете с итераторами, itertools является достойным дополнением к вашему набору инструментов.

Что произойдет, если next(it) был исчерпан и вызовет StopIteration?

(т.е. когдаit имел меньше чем n значений, чтобы получить)

Когда я писал вышеупомянутую строку пару лет назад, я, вероятно, думал, что StopIteration будет иметь умный побочный эффект от чистого прекращения понимания списка.Но нет, все понимание рухнет, пройдя StopIteration вверх.(Он будет завершен без ошибок, только если исключение возникло из итератора range(n).)

Это, вероятно, не то поведение, которое вам нужно.

Но оно ухудшается.Следующее должно быть эквивалентно пониманию списка (особенно в Python 3):

list(next(it) for _ in range(n))

Это не так.Внутренняя часть является сокращением для функции генератора;list() знает, что это сделано, когда оно вызывает StopIteration в любом месте .
=> Эта версия благополучно справляется, когда нет n значений, и возвращает более короткий список.(Как itertools.islice().)

[Казни: 2,7 , 3,4 ]

Но это тоже изменится!Тот факт, что генератор молча завершает работу, когда любой код внутри него поднимает StopIteration, является известной бородавкой, адресуемой PEP 479 .Начиная с Python 3.7 (или 3.5 с будущим импортом), это вызовет RuntimeError вместо чистой доработки генератора.Т.е. это станет похоже на поведение понимания списка.(Проверено на последней сборке HEAD)

3 голосов
/ 11 ноября 2010
for word, i in zip(word_reader(file), xrange(n)):
    ...
2 голосов
/ 03 января 2018

Чтобы получить первые n значений генератора, вы можете использовать more_itertools.take .

Если вы планируете перебирать слова по частям (например, 100 за раз)Вы можете использовать more_itertools.chunked (https://more -itertools.readthedocs.io / en / latest / api.html ):

import more_itertools
for words in more_itertools.chunked(reader, n=100):
    # process 100 words
0 голосов
/ 17 марта 2019

Использование cytoolz.take .

>>> from cytoolz import take
>>> list(take(2, [10, 20, 30, 40, 50]))
[10, 20]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...