Instead of using 3 loops separately, I'd like to use only one loop and speed up the code.
There are 3 different patterns of range(0,150)
, increasing 3 per loop:
0,3,6,9...
1,4,7,10...
2,5,8,11....
My code:
fromlist = [1,2,3,4,5]
req1list = ['z','t','y']
req2list = [21,39,52]
req3list = [100,200,300]
for i in range(0,150,3):
req1list.append(fromlist[i])
for j in range(1,150,3):
req2list.append(fromlist[j])
for x in range(2,151,3):
req3list.append(fromlist[x])
Note that lists are already created and there is data inside the file. Thus, I thought that list comprehension would be impossible.
Another note: please ignore the list lengths, in my file the lists are far longer and don't cause errors in []
.
Is there any way that unites these 3 loops in one, and speed up the code?
CodePudding user response:
Instead of trying to perform three appends in each iteration (in one loop), you'll get faster results if you call extend
instead of append
. You could also use slicing to avoid comprehension:
req1list.extend(fromlist[::3])
req2list.extend(fromlist[1::3])
req3list.extend(fromlist[2::3])
And if it is important to stop at 150, add it in the slice operation:
req1list.extend(fromlist[:150:3])
# ...etc
CodePudding user response:
A slightly different approach would be to use the grouper
function defined in the itertools
documentation.
def grouper(iterable, n, *, incomplete='fill', fillvalue=None):
args = [iter(iterable)] * n
if incomplete == 'fill':
return zip_longest(*args, fillvalue=fillvalue)
if incomplete == 'strict':
return zip(*args, strict=True)
if incomplete == 'ignore':
return zip(*args)
else:
raise ValueError('Expected fill, strict, or ignore')
With this, you can write
for x, y, z in grouper(fromlist, 3):
req1list.append(x)
req2list.append(y)
req3list.append(z)
(You can copy the definition of grouper
from the documentation to your own code, or use the third-party more-itertools
package which includes it and many more useful functions for dealing with iterators.)