Повторите числа, используя itertools - PullRequest
1 голос
/ 06 марта 2020

Я изучал itertools и столкнулся с интересной проблемой.

Как получить следующий результат?

nums = [1,2,3,4]
# logic:  i+1 th number is repeated i times.
          2 is repeated 1 times and 4 is repeated 3 times.

required = [2,4,4,4] 

Моя попытка

import itertools

nums = [1,2,3,4]
nums[::2]  # [1,3]
nums[1::2] # [2,4]
              * 2 is repeated 1 times
                * 4 is repeated 3 times and makes [2,4,4,4]

list(itertools.starmap(itertools.repeat, zip(nums[::2],nums[1::2])))

Gives,
[repeat(1, 2), repeat(3, 4)]

How to get:
required = [2,4,4,4]

Требуется

From: [1,2,3,4]
To:   [2,4,4,4]

We can use itertools, list comp and numpy.
With emphasis on itertools, since I am learning itertools functions
such as repeat, starmap and so on.

Ответы [ 3 ]

4 голосов
/ 06 марта 2020

repeat создает итеративный объект, поэтому вам нужно объединить эти итераторы в цепочку, а перед созданием списка выполнить итерацию по результату. (Вам также нужно поменять аргументы на zip)

>>> from itertools import starmap, repeat, chain
>>> list(<b>chain.from_iterable(</b>starmap(repeat, zip(nums[<b>1</b>::2], nums[::2]))<b>)</b>)
[2, 4, 4, 4]

На самом деле вам не нужны ни starmap, ни zip; map может применить многопараметрическую функцию к нескольким итераторам, принимая по одному аргументу от каждого итератора за вызов.

>>> list(chain.from_iterable(map(repeat, nums[1::2], nums[::2])))
[2, 4, 4, 4]

Продвигаясь на один шаг дальше в itertools land, вы можете использовать tee и islice чтобы избежать создания двух временных списков с помощью нарезки nums (хотя при этом в одной строке возникает беспорядок):

>>> from itertools import tee, islice
>>> t1, t2 = tee(nums)
>>> list(chain.from_iterable(map(repeat, <b>islice(t1, 1, None, 2)</b>, <b>islice(t2, None, None, 2)</b>)))
[2, 4, 4, 4]
3 голосов
/ 06 марта 2020

вам не нужны itertools для этого. Достаточно понимания списка и zip:

nums = [1,2,3,4]

rnums = [ rn for r,n in zip(nums[::2],nums[1::2]) for rn in r*[n] ]

print(rnums) # [2, 4, 4, 4]

[EDIT]: использование itertools:

nums = [*chain(*map(repeat,zip(nums[::2],nums[1::2])))]
2 голосов
/ 06 марта 2020

Если вы хотите go просто, без itertools, без понимания списка, это можно сделать очень просто, как это:

nums = [1,2,3,4]
ans = []
for i in range(len(nums)):
    if i%2: # odd index
        ans += [ nums[i] ] * nums[i-1]

Использование списка comp

sum(([nums[i+1]]*nums[i] for i in range(0, len(nums), 2)), [])
...