I moved most of the indexing into a range()
computation. Its faster then manifesting the indexes into a sublist - see timing down below:
sb = [11,12,21,22,31,32]*4 #stream buffer, e.g. 4 identical frames
ci = 1 #1-indexed channel index
cs = 2 #channel size
nc = 3 #number of channels in each frame
fs = nc*cs #frame size
for ci in range(1,4):
print [x for y in [sb[x:x+cs] for x in range((ci-1)*cs,len(sb),fs)] for x in y]
Output:
[11, 12, 11, 12, 11, 12, 11, 12]
[21, 22, 21, 22, 21, 22, 21, 22]
[31, 32, 31, 32, 31, 32, 31, 32]
I moved most of the work into the range()
call - producing list of sublists, the rest is a simple decomposition of the sublists into one list.
range((ci-1)*cs,len(sb), fs)
| | |________ frame size, range will use steps the size of the frame
| |______________ till end of data
|________________________ starting at (ci-1) * channel size
for ci = 1 it starts at 0, 6,12,18,....
for ci = 2 it starts at 2, 8,14,....
for ci = 3 it starts at 4, 10,...
for ci = 4 it starts at 6, ...
and increases by fs = 6 until end of data. The list comp then gets a sublist of len cs
and the rest of the list-comp flattens it down from list of list to a simpler list
Timing:
import timeit
print timeit.timeit(stmt='''
sb = [11,12,21,22,31,32]*4*5 #stream buffer, e.g. 4 identical frames
ci = 1 #1-indexed channel index
cs = 2 #channel size
nc = 3 #number of channels in each frame
fs = nc*cs #frame size
for ci in range(1,4):
[x for y in [sb[x:x+cs] for x in range((ci-1)*cs,len(sb),fs)] for x in y]
''', setup='pass', number=10000) # 0.588474035263
print timeit.timeit(stmt='''
sb = [11,12,21,22,31,32]*4*5 #stream buffer, e.g. 4 identical frames
ci = 1 #1-indexed channel index
cs = 2 #channel size
nc = 3 #number of channels in each frame
fs = nc*cs #frame size
for ci in range(1,4):
[i for l in [sb[j+ci-1:j+ci-1+cs] for j in [x*fs+ci-1 for x in xrange(len(sb)/fs)]] for i in l]
''', setup='pass', number=10000) # 0.734045982361