Reputation: 7026
What is the easiest way to construct a list of consecutive integers in given ranges, like this?
[1,2,3,4,5,6,7, 15,16,17,18,19, 56,57,58,59]
I know the start and end values of each group. I tried this:
ranges = ( range(1,8),
range(15,20),
range(56,60) )
Y = sum( [ list(x) for x in ranges ] )
which works, but seems like a mouthful. And in terms of code legibility, the sum()
is just confusing. In MATLAB it's just
Y = [ 1:7, 15:19, 56:59 ]
Is there an better way? Can use numpy
if easier.
Can anybody explain why it doesn't work if I use a generator for the sum
?
Y = sum( (list(x) for x in ranges) )
TypeError: unsupported operand types for +: 'int' and 'list'
Seems like it doesn't know the starting value should be []
rather than 0
!
Upvotes: 1
Views: 919
Reputation: 106455
To fix your code with sum
, you can specify an empty list as the start
keyword argument as the starting point of aggregation:
sum((list(x) for x in ranges), start=[])
Upvotes: 2
Reputation: 610
You could you use itertool's chain.from_iterable, which lazily evaluates the args from a single interable:
>>> list(itertools.chain.from_iterable((range(1,8), range(15,20), range(56,60))))
[1, 2, 3, 4, 5, 6, 7, 15, 16, 17, 18, 19, 56, 57, 58, 59]
Upvotes: 2
Reputation: 260360
The matlab syntax has it's equivalent in numpy with numpy.r_
:
import numpy as np
np.r_[1:7, 15:19, 56:59]
output: array([ 1, 2, 3, 4, 5, 6, 15, 16, 17, 18, 56, 57, 58])
For a list:
np.r_[1:7, 15:19, 56:59].tolist()
output: [1, 2, 3, 4, 5, 6, 15, 16, 17, 18, 56, 57, 58]
Upvotes: 4
Reputation: 168841
You could write your own generator helper function:
def ranges(*argses):
for args in argses:
yield from range(*args)
for x in ranges((1, 7), (15, 19), (56, 59)):
print(x)
If you need an actual list out of those multi-ranges, then list(ranges(...))
.
Upvotes: 1
Reputation: 5802
One option, and maybe the closest to the Matlab syntax, is to use the star operator:
>>> [*range(1,8), *range(15,20), *range(56, 60)]
[1, 2, 3, 4, 5, 6, 7, 15, 16, 17, 18, 19, 56, 57, 58, 59]
Upvotes: 6