Повторите значения без вложенного цикла for - PullRequest
0 голосов
/ 11 февраля 2020

Мне было интересно, смогу ли я избежать вложенности для l oop и использовать один из бесконечных итераторов из модуля itertools , например cycle или repeat, чтобы получить ожидаемый результат?

Значение l oop должно быть бесконечным, поскольку значение остановки для шага заранее неизвестно.

Test:

$ python3 test.py 
Expected output:
A 0
B 0
C 0
A 100
B 100
C 100
A 200
B 200
C 200
A 300
B 300
C 300
A 400
B 400
C 400
A 500
B 500
C 500
Incorrect output:
A 0
B 100
C 200
A 300
B 400
C 500
A 600

test. py:

from itertools import count, cycle, repeat


STEP = 100 
LIMIT = 500
TEAMS = ['A', 'B', 'C']

def test01():
    for step in count(0, STEP):
        for team in TEAMS:
            print(team, step)
        if step >= LIMIT: # Limit for testing
            break

def test02():
    for team, step in zip(cycle(TEAMS), count(0, STEP)):
        print(team, step)
        if step > LIMIT: # Limit for testing
            break

def main():
    print('Expected output:')
    test01()
    print('Incorrect output:')
    test02()

if __name__ == "__main__":
    main()

Ответы [ 2 ]

5 голосов
/ 11 февраля 2020

Попробуйте itertools.product

from itertools import product
for i, j in product(range(0, 501, 100), 'ABC'):
    print(j, i)

Как говорят документы, product(A, B) эквивалентно ((x,y) for x in A for y in B). Как видите, product дает кортеж, что означает, что это генератор, и не создает список в памяти для правильной работы.

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

def product(*args, **kwds):
    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
    pools = map(tuple, args) * kwds.get('repeat', 1)
    result = [[]]
    for pool in pools:
        result = [x+[y] for x in result for y in pool]
    for prod in result:
        yield tuple(prod)

Но вы не можете использовать itertools.product для бесконечного l oop из-за известной проблемы :

Согласно документации, itertools.product эквивалентен вложенным циклам for в выражении генератора. Но itertools.product (itertools.count (2010)) не является.

>>> import itertools
>>> (year for year in itertools.count(2010))
<generator object <genexpr> at 0x026367D8>
>>> itertools.product(itertools.count(2010))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
MemoryError

Входные данные для itertools.product должны быть конечной последовательностью конечных итерируемых элементов.

Для бесконечно l oop, вы можете использовать этот код .

0 голосов
/ 11 февраля 2020

Ответ от tomjn лучший для конечного l oop, поэтому этот ответ на всякий случай, если вы не хотите использовать itertools.product (для бесконечного l oop):

def with_generator():
    """
    For infinite loop
    """
    for i, j in ((step, team) for step in count(0, 100) for team in 'ABC'):
        print(j, i)
...