I am trying to get m values while stepping through every n elements of an array. For example, for m = 2 and n = 5, and given
我试图在逐步遍历数组的每个n元素时获取m值。例如,对于m = 2和n = 5,并给出
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
I want to retrieve
我想要检索
b = [1, 2, 6, 7]
Is there a way to do this using slicing? I can do this using a nested list comprehension, but I was wondering if there was a way to do this using the indices only. For reference, the list comprehension way is:
有没有办法使用切片来做到这一点?我可以使用嵌套列表理解来做到这一点,但我想知道是否有办法只使用索引来做到这一点。作为参考,列表理解方式是:
b = [k for j in [a[i:i+2] for i in range(0,len(a),5)] for k in j]
7 个解决方案
#1
23
I agree with wim that you can't do it with just slicing. But you can do it with just one list comprehension:
我同意wim你不能只用切片来做。但是你可以只用一个列表理解来做到这一点:
>>> [x for i,x in enumerate(a) if i%n < m]
[1, 2, 6, 7]
#2
6
No, that is not possible with slicing. Slicing only supports start, stop, and step - there is no way to represent stepping with "groups" of size larger than 1.
不,切片不可能。切片仅支持开始,停止和步骤 - 无法用大于1的“组”表示步进。
#3
5
In short, no, you cannot. But you can use itertools
to remove the need for intermediary lists:
总之,不,你不能。但是你可以使用itertools来消除对中间列表的需求:
from itertools import chain, islice
res = list(chain.from_iterable(islice(a, i, i+2) for i in range(0, len(a), 5)))
print(res)
[1, 2, 6, 7]
Borrowing @Kevin's logic, if you want a vectorised solution to avoid a for
loop, you can use 3rd party library numpy
:
借用@Kevin的逻辑,如果你想要一个矢量化的解决方案来避免for循环,你可以使用第三方库numpy:
import numpy as np
m, n = 2, 5
a = np.array(a) # convert to numpy array
res = a[np.where(np.arange(a.shape[0]) % n < m)]
#4
3
There are other ways to do it, which all have advantages for some cases, but none are "just slicing".
还有其他方法可以做到这一点,在某些情况下都有优势,但没有一种方法只是“切片”。
The most general solution is probably to group your input, slice the groups, then flatten the slices back out. One advantage of this solution is that you can do it lazily, without building big intermediate lists, and you can do it to any iterable, including a lazy iterator, not just a list.
最通用的解决方案可能是对输入进行分组,对组进行切片,然后将切片展平。这个解决方案的一个优点是你可以懒惰地完成它,而不需要构建大的中间列表,你可以对任何迭代执行它,包括一个惰性迭代器,而不仅仅是一个列表。
# from itertools recipes in the docs
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return itertools.zip_longest(*args, fillvalue=fillvalue)
groups = grouper(a, 5)
truncated = (group[:2] for group in groups)
b = [elem for group in truncated for elem in group]
And you can convert that into a pretty simple one-liner, although you still need the grouper
function:
你可以把它转换成一个非常简单的单行,虽然你仍然需要石斑鱼功能:
b = [elem for group in grouper(a, 5) for elem in group[:2]]
Another option is to build a list of indices, and use itemgetter
to grab all the values. This might be more readable for a more complicated function than just "the first 2 of every 5", but it's probably less readable for something as simple as your use:
另一种选择是构建索引列表,并使用itemgetter获取所有值。对于更复杂的功能而言,这可能比“每5个中的前2个”更具可读性,但对于像您使用这样简单的东西,它可能不太可读:
indices = [i for i in range(len(a)) if i%5 < 2]
b = operator.itemgetter(*indices)(a)
… which can be turned into a one-liner:
......可以变成单线:
b = operator.itemgetter(*[i for i in range(len(a)) if i%5 < 2])(a)
And you can combine the advantages of the two approaches by writing your own version of itemgetter
that takes a lazy index iterator—which I won't show, because you can go even better by writing one that takes an index filter function instead:
你可以通过编写自己的itemgetter版本来结合这两种方法的优点,这个项目采用一个懒惰的索引迭代器 - 我不会展示它,因为你可以通过编写一个采用索引过滤器函数的方法来做得更好:
def indexfilter(pred, a):
return [elem for i, elem in enumerate(a) if pred(i)]
b = indexfilter((lambda i: i%5<2), a)
(To make indexfilter
lazy, just replace the brackets with parens.)
(要使indexfilter变得懒惰,只需用parens替换括号。)
… or, as a one-liner:
......或者,作为一个班轮:
b = [elem for i, elem in enumerate(a) if i%5<2]
I think this last one might be the most readable. And it works with any iterable rather than just lists, and it can be made lazy (again, just replace the brackets with parens). But I still don't think it's simpler than your original comprehension, and it's not just slicing.
我认为最后一个可能是最具可读性的。它适用于任何可迭代而不仅仅是列表,并且它可以变得懒惰(再次,只需用parens替换括号)。但我仍然认为它不比你原来的理解简单,而且它不仅仅是切片。
#5
2
The question states array, and by that if we are talking about NumPy arrays, we can surely use few obvious NumPy tricks and few not-so obvious ones. We can surely use slicing
to get a 2D view into the input under certain conditions.
这个问题陈述了数组,如果我们讨论的是NumPy数组,我们肯定会使用一些明显的NumPy技巧,而很少有那么明显的技巧。我们当然可以使用切片在特定条件下将2D视图输入到输入中。
Now, based on the array length, let's call it l
and m
, we would have three scenarios :
现在,根据数组长度,我们称之为l和m,我们将有三种情况:
Scenario #1 :l
is divisible by n
We can use slicing and reshaping to get a view into the input array and hence get constant runtime.
我们可以使用切片和整形来获取输入数组的视图,从而获得恒定的运行时间。
Verify the view concept :
验证视图概念:
In [108]: a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
In [109]: m = 2; n = 5
In [110]: a.reshape(-1,n)[:,:m]
Out[110]:
array([[1, 2],
[6, 7]])
In [111]: np.shares_memory(a, a.reshape(-1,n)[:,:m])
Out[111]: True
Check timings on a very large array and hence constant runtime claim :
检查非常大的数组上的时序,因此持续运行时声明:
In [118]: a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
In [119]: %timeit a.reshape(-1,n)[:,:m]
1000000 loops, best of 3: 563 ns per loop
In [120]: a = np.arange(10000000)
In [121]: %timeit a.reshape(-1,n)[:,:m]
1000000 loops, best of 3: 564 ns per loop
To get flattened version :
要获得扁平版本:
If we have to get a flattened array as output, we just need to use a flattening operation with .ravel()
, like so -
如果我们必须得到一个扁平数组作为输出,我们只需要使用.ravel()的展平操作,就像这样 -
In [127]: a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
In [128]: m = 2; n = 5
In [129]: a.reshape(-1,n)[:,:m].ravel()
Out[129]: array([1, 2, 6, 7])
Timings show that it's not too bad when compared with the other looping and vectorized numpy.where versions from other posts -
Timings表明,与其他帖子的其他循环和矢量化numpy.where版本相比,它并不太糟糕 -
In [143]: a = np.arange(10000000)
# @Kevin's soln
In [145]: %timeit [x for i,x in enumerate(a) if i%n < m]
1 loop, best of 3: 1.23 s per loop
# @jpp's soln
In [147]: %timeit a[np.where(np.arange(a.shape[0]) % n < m)]
10 loops, best of 3: 145 ms per loop
In [144]: %timeit a.reshape(-1,n)[:,:m].ravel()
100 loops, best of 3: 16.4 ms per loop
Scenario #2 :l
is not divisible by n
, but the groups end with a complete one at the end
We go to the non-obvious NumPy methods with np.lib.stride_tricks.as_strided
that allows to go beyoond the memory block bounds (hence we need to be careful here to not write into those) to facilitate a solution using slicing
. The implementation would look something like this -
我们使用np.lib.stride_tricks.as_strided转到非显而易见的NumPy方法,它允许beyoond内存块边界(因此我们需要注意不要写入那些)以促进使用切片的解决方案。实现看起来像这样 -
def select_groups(a, m, n):
a = np.asarray(a)
strided = np.lib.stride_tricks.as_strided
# Get params defining the lengths for slicing and output array shape
nrows = len(a)//n
add0 = len(a)%n
s = a.strides[0]
out_shape = nrows+int(add0!=0),m
# Finally stride, flatten with reshape and slice
return strided(a, shape=out_shape, strides=(s*n,s))
A sample run to verify that the output is a view
-
运行示例以验证输出是否为视图 -
In [151]: a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13])
In [152]: m = 2; n = 5
In [153]: select_groups(a, m, n)
Out[153]:
array([[ 1, 2],
[ 6, 7],
[11, 12]])
In [154]: np.shares_memory(a, select_groups(a, m, n))
Out[154]: True
To get flattened version, append with .ravel()
.
要获得展平版本,请使用.ravel()附加。
Let's get some timings comparison -
让我们来看一些时间比较 -
In [158]: a = np.arange(10000003)
In [159]: m = 2; n = 5
# @Kevin's soln
In [161]: %timeit [x for i,x in enumerate(a) if i%n < m]
1 loop, best of 3: 1.24 s per loop
# @jpp's soln
In [162]: %timeit a[np.where(np.arange(a.shape[0]) % n < m)]
10 loops, best of 3: 148 ms per loop
In [160]: %timeit select_groups(a, m=m, n=n)
100000 loops, best of 3: 5.8 µs per loop
If we need a flattened version, it's still not too bad -
如果我们需要一个扁平版本,它仍然不是太糟糕 -
In [163]: %timeit select_groups(a, m=m, n=n).ravel()
100 loops, best of 3: 16.5 ms per loop
Scenario #3 :l
is not divisible by n
,and the groups end with a incomplete one at the end
For this case, we would need an extra slicing at the end on top of what we had in the previous method, like so -
对于这种情况,我们需要在前一个方法的最后加上一个额外的切片,就像这样 -
def select_groups_generic(a, m, n):
a = np.asarray(a)
strided = np.lib.stride_tricks.as_strided
# Get params defining the lengths for slicing and output array shape
nrows = len(a)//n
add0 = len(a)%n
lim = m*(nrows) + add0
s = a.strides[0]
out_shape = nrows+int(add0!=0),m
# Finally stride, flatten with reshape and slice
return strided(a, shape=out_shape, strides=(s*n,s)).reshape(-1)[:lim]
Sample run -
样品运行 -
In [166]: a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
In [167]: m = 2; n = 5
In [168]: select_groups_generic(a, m, n)
Out[168]: array([ 1, 2, 6, 7, 11])
Timings -
计时 -
In [170]: a = np.arange(10000001)
In [171]: m = 2; n = 5
# @Kevin's soln
In [172]: %timeit [x for i,x in enumerate(a) if i%n < m]
1 loop, best of 3: 1.23 s per loop
# @jpp's soln
In [173]: %timeit a[np.where(np.arange(a.shape[0]) % n < m)]
10 loops, best of 3: 145 ms per loop
In [174]: %timeit select_groups_generic(a, m, n)
100 loops, best of 3: 12.2 ms per loop
#6
0
I realize that recursion isn't popular, but would something like this work? Also, uncertain if adding recursion to the mix counts as just using slices.
我意识到递归并不受欢迎,但这样的工作呢?此外,不确定添加递归到混合计数只是使用切片。
def get_elements(A, m, n):
if(len(A) < m):
return A
else:
return A[:m] + get_elements(A[n:], m, n)
A is the array, m and n are defined as in the question. The first if covers the base case, where you have an array with length less than the number of elements you're trying to retrieve, and the second if is the recursive case. I'm somewhat new to python, please forgive my poor understanding of the language if this doesn't work properly, though I tested it and it seems to work fine.
A是数组,m和n在问题中定义。第一个if覆盖基本情况,其中有一个数组,其长度小于您尝试检索的元素数,第二个if是递归情况。我对python有些新意,请原谅我对语言的不了解,如果这不能正常工作,虽然我测试过它似乎工作正常。
#7
0
With itertools you could get an iterator with:
使用itertools你可以得到一个迭代器:
from itertools import compress, cycle
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
n = 5
m = 2
it = compress(a, cycle([1, 1, 0, 0, 0]))
res = list(it)
#1
23
I agree with wim that you can't do it with just slicing. But you can do it with just one list comprehension:
我同意wim你不能只用切片来做。但是你可以只用一个列表理解来做到这一点:
>>> [x for i,x in enumerate(a) if i%n < m]
[1, 2, 6, 7]
#2
6
No, that is not possible with slicing. Slicing only supports start, stop, and step - there is no way to represent stepping with "groups" of size larger than 1.
不,切片不可能。切片仅支持开始,停止和步骤 - 无法用大于1的“组”表示步进。
#3
5
In short, no, you cannot. But you can use itertools
to remove the need for intermediary lists:
总之,不,你不能。但是你可以使用itertools来消除对中间列表的需求:
from itertools import chain, islice
res = list(chain.from_iterable(islice(a, i, i+2) for i in range(0, len(a), 5)))
print(res)
[1, 2, 6, 7]
Borrowing @Kevin's logic, if you want a vectorised solution to avoid a for
loop, you can use 3rd party library numpy
:
借用@Kevin的逻辑,如果你想要一个矢量化的解决方案来避免for循环,你可以使用第三方库numpy:
import numpy as np
m, n = 2, 5
a = np.array(a) # convert to numpy array
res = a[np.where(np.arange(a.shape[0]) % n < m)]
#4
3
There are other ways to do it, which all have advantages for some cases, but none are "just slicing".
还有其他方法可以做到这一点,在某些情况下都有优势,但没有一种方法只是“切片”。
The most general solution is probably to group your input, slice the groups, then flatten the slices back out. One advantage of this solution is that you can do it lazily, without building big intermediate lists, and you can do it to any iterable, including a lazy iterator, not just a list.
最通用的解决方案可能是对输入进行分组,对组进行切片,然后将切片展平。这个解决方案的一个优点是你可以懒惰地完成它,而不需要构建大的中间列表,你可以对任何迭代执行它,包括一个惰性迭代器,而不仅仅是一个列表。
# from itertools recipes in the docs
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return itertools.zip_longest(*args, fillvalue=fillvalue)
groups = grouper(a, 5)
truncated = (group[:2] for group in groups)
b = [elem for group in truncated for elem in group]
And you can convert that into a pretty simple one-liner, although you still need the grouper
function:
你可以把它转换成一个非常简单的单行,虽然你仍然需要石斑鱼功能:
b = [elem for group in grouper(a, 5) for elem in group[:2]]
Another option is to build a list of indices, and use itemgetter
to grab all the values. This might be more readable for a more complicated function than just "the first 2 of every 5", but it's probably less readable for something as simple as your use:
另一种选择是构建索引列表,并使用itemgetter获取所有值。对于更复杂的功能而言,这可能比“每5个中的前2个”更具可读性,但对于像您使用这样简单的东西,它可能不太可读:
indices = [i for i in range(len(a)) if i%5 < 2]
b = operator.itemgetter(*indices)(a)
… which can be turned into a one-liner:
......可以变成单线:
b = operator.itemgetter(*[i for i in range(len(a)) if i%5 < 2])(a)
And you can combine the advantages of the two approaches by writing your own version of itemgetter
that takes a lazy index iterator—which I won't show, because you can go even better by writing one that takes an index filter function instead:
你可以通过编写自己的itemgetter版本来结合这两种方法的优点,这个项目采用一个懒惰的索引迭代器 - 我不会展示它,因为你可以通过编写一个采用索引过滤器函数的方法来做得更好:
def indexfilter(pred, a):
return [elem for i, elem in enumerate(a) if pred(i)]
b = indexfilter((lambda i: i%5<2), a)
(To make indexfilter
lazy, just replace the brackets with parens.)
(要使indexfilter变得懒惰,只需用parens替换括号。)
… or, as a one-liner:
......或者,作为一个班轮:
b = [elem for i, elem in enumerate(a) if i%5<2]
I think this last one might be the most readable. And it works with any iterable rather than just lists, and it can be made lazy (again, just replace the brackets with parens). But I still don't think it's simpler than your original comprehension, and it's not just slicing.
我认为最后一个可能是最具可读性的。它适用于任何可迭代而不仅仅是列表,并且它可以变得懒惰(再次,只需用parens替换括号)。但我仍然认为它不比你原来的理解简单,而且它不仅仅是切片。
#5
2
The question states array, and by that if we are talking about NumPy arrays, we can surely use few obvious NumPy tricks and few not-so obvious ones. We can surely use slicing
to get a 2D view into the input under certain conditions.
这个问题陈述了数组,如果我们讨论的是NumPy数组,我们肯定会使用一些明显的NumPy技巧,而很少有那么明显的技巧。我们当然可以使用切片在特定条件下将2D视图输入到输入中。
Now, based on the array length, let's call it l
and m
, we would have three scenarios :
现在,根据数组长度,我们称之为l和m,我们将有三种情况:
Scenario #1 :l
is divisible by n
We can use slicing and reshaping to get a view into the input array and hence get constant runtime.
我们可以使用切片和整形来获取输入数组的视图,从而获得恒定的运行时间。
Verify the view concept :
验证视图概念:
In [108]: a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
In [109]: m = 2; n = 5
In [110]: a.reshape(-1,n)[:,:m]
Out[110]:
array([[1, 2],
[6, 7]])
In [111]: np.shares_memory(a, a.reshape(-1,n)[:,:m])
Out[111]: True
Check timings on a very large array and hence constant runtime claim :
检查非常大的数组上的时序,因此持续运行时声明:
In [118]: a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
In [119]: %timeit a.reshape(-1,n)[:,:m]
1000000 loops, best of 3: 563 ns per loop
In [120]: a = np.arange(10000000)
In [121]: %timeit a.reshape(-1,n)[:,:m]
1000000 loops, best of 3: 564 ns per loop
To get flattened version :
要获得扁平版本:
If we have to get a flattened array as output, we just need to use a flattening operation with .ravel()
, like so -
如果我们必须得到一个扁平数组作为输出,我们只需要使用.ravel()的展平操作,就像这样 -
In [127]: a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
In [128]: m = 2; n = 5
In [129]: a.reshape(-1,n)[:,:m].ravel()
Out[129]: array([1, 2, 6, 7])
Timings show that it's not too bad when compared with the other looping and vectorized numpy.where versions from other posts -
Timings表明,与其他帖子的其他循环和矢量化numpy.where版本相比,它并不太糟糕 -
In [143]: a = np.arange(10000000)
# @Kevin's soln
In [145]: %timeit [x for i,x in enumerate(a) if i%n < m]
1 loop, best of 3: 1.23 s per loop
# @jpp's soln
In [147]: %timeit a[np.where(np.arange(a.shape[0]) % n < m)]
10 loops, best of 3: 145 ms per loop
In [144]: %timeit a.reshape(-1,n)[:,:m].ravel()
100 loops, best of 3: 16.4 ms per loop
Scenario #2 :l
is not divisible by n
, but the groups end with a complete one at the end
We go to the non-obvious NumPy methods with np.lib.stride_tricks.as_strided
that allows to go beyoond the memory block bounds (hence we need to be careful here to not write into those) to facilitate a solution using slicing
. The implementation would look something like this -
我们使用np.lib.stride_tricks.as_strided转到非显而易见的NumPy方法,它允许beyoond内存块边界(因此我们需要注意不要写入那些)以促进使用切片的解决方案。实现看起来像这样 -
def select_groups(a, m, n):
a = np.asarray(a)
strided = np.lib.stride_tricks.as_strided
# Get params defining the lengths for slicing and output array shape
nrows = len(a)//n
add0 = len(a)%n
s = a.strides[0]
out_shape = nrows+int(add0!=0),m
# Finally stride, flatten with reshape and slice
return strided(a, shape=out_shape, strides=(s*n,s))
A sample run to verify that the output is a view
-
运行示例以验证输出是否为视图 -
In [151]: a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13])
In [152]: m = 2; n = 5
In [153]: select_groups(a, m, n)
Out[153]:
array([[ 1, 2],
[ 6, 7],
[11, 12]])
In [154]: np.shares_memory(a, select_groups(a, m, n))
Out[154]: True
To get flattened version, append with .ravel()
.
要获得展平版本,请使用.ravel()附加。
Let's get some timings comparison -
让我们来看一些时间比较 -
In [158]: a = np.arange(10000003)
In [159]: m = 2; n = 5
# @Kevin's soln
In [161]: %timeit [x for i,x in enumerate(a) if i%n < m]
1 loop, best of 3: 1.24 s per loop
# @jpp's soln
In [162]: %timeit a[np.where(np.arange(a.shape[0]) % n < m)]
10 loops, best of 3: 148 ms per loop
In [160]: %timeit select_groups(a, m=m, n=n)
100000 loops, best of 3: 5.8 µs per loop
If we need a flattened version, it's still not too bad -
如果我们需要一个扁平版本,它仍然不是太糟糕 -
In [163]: %timeit select_groups(a, m=m, n=n).ravel()
100 loops, best of 3: 16.5 ms per loop
Scenario #3 :l
is not divisible by n
,and the groups end with a incomplete one at the end
For this case, we would need an extra slicing at the end on top of what we had in the previous method, like so -
对于这种情况,我们需要在前一个方法的最后加上一个额外的切片,就像这样 -
def select_groups_generic(a, m, n):
a = np.asarray(a)
strided = np.lib.stride_tricks.as_strided
# Get params defining the lengths for slicing and output array shape
nrows = len(a)//n
add0 = len(a)%n
lim = m*(nrows) + add0
s = a.strides[0]
out_shape = nrows+int(add0!=0),m
# Finally stride, flatten with reshape and slice
return strided(a, shape=out_shape, strides=(s*n,s)).reshape(-1)[:lim]
Sample run -
样品运行 -
In [166]: a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
In [167]: m = 2; n = 5
In [168]: select_groups_generic(a, m, n)
Out[168]: array([ 1, 2, 6, 7, 11])
Timings -
计时 -
In [170]: a = np.arange(10000001)
In [171]: m = 2; n = 5
# @Kevin's soln
In [172]: %timeit [x for i,x in enumerate(a) if i%n < m]
1 loop, best of 3: 1.23 s per loop
# @jpp's soln
In [173]: %timeit a[np.where(np.arange(a.shape[0]) % n < m)]
10 loops, best of 3: 145 ms per loop
In [174]: %timeit select_groups_generic(a, m, n)
100 loops, best of 3: 12.2 ms per loop
#6
0
I realize that recursion isn't popular, but would something like this work? Also, uncertain if adding recursion to the mix counts as just using slices.
我意识到递归并不受欢迎,但这样的工作呢?此外,不确定添加递归到混合计数只是使用切片。
def get_elements(A, m, n):
if(len(A) < m):
return A
else:
return A[:m] + get_elements(A[n:], m, n)
A is the array, m and n are defined as in the question. The first if covers the base case, where you have an array with length less than the number of elements you're trying to retrieve, and the second if is the recursive case. I'm somewhat new to python, please forgive my poor understanding of the language if this doesn't work properly, though I tested it and it seems to work fine.
A是数组,m和n在问题中定义。第一个if覆盖基本情况,其中有一个数组,其长度小于您尝试检索的元素数,第二个if是递归情况。我对python有些新意,请原谅我对语言的不了解,如果这不能正常工作,虽然我测试过它似乎工作正常。
#7
0
With itertools you could get an iterator with:
使用itertools你可以得到一个迭代器:
from itertools import compress, cycle
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
n = 5
m = 2
it = compress(a, cycle([1, 1, 0, 0, 0]))
res = list(it)