Concatenating two range function results
Does range function allows concatenation ? Like i want to make a range(30)
& concatenate it with range(2000, 5002)
. So my concatenated range will be 0, 1, 2, ... 29, 2000, 2001, ... 5001
Code like this does not work on my latest python (ver: 3.3.0)
range(30) + range(2000, 5002)
You can use itertools.chain
for this:
from itertools import chain
concatenated = chain(range(30), range(2000, 5002))
for i in concatenated:
...
It works for arbitrary iterables. Note that there's a difference in behavior of range()
between Python 2 and 3 that you should know about: in Python 2 range
returns a list, and in Python3 an iterator, which is memory-efficient, but not always desirable.
Lists can be concatenated with +
, iterators cannot.
I like the most simple solutions that are possible (including efficiency). It is not always clear whether the solution is such. Anyway, the range()
in Python 3 is a generator. You can wrap it to any construct that does iteration. The list()
is capable of construction of a list value from any iterable. The +
operator for lists does concatenation. I am using smaller values in the example:
>>> list(range(5))
[0, 1, 2, 3, 4]
>>> list(range(10, 20))
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> list(range(5)) + list(range(10,20))
[0, 1, 2, 3, 4, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
This is what range(5) + range(10, 20)
exactly did in Python 2.5 -- because range()
returned a list.
In Python 3, it is only useful if you really want to construct the list. Otherwise, I recommend the Lev Levitsky's solution with itertools.chain. The documentation also shows the very straightforward implementation:
def chain(*iterables):
# chain('ABC', 'DEF') --> A B C D E F
for it in iterables:
for element in it:
yield element
The solution by Inbar Rose is fine and functionally equivalent. Anyway, my +1 goes to Lev Levitsky and to his argument about using the standard libraries. From The Zen of Python...
In the face of ambiguity, refuse the temptation to guess.
#!python3
import timeit
number = 10000
t = timeit.timeit('''\
for i in itertools.chain(range(30), range(2000, 5002)):
pass
''',
'import itertools', number=number)
print('itertools:', t/number * 1000000, 'microsec/one execution')
t = timeit.timeit('''\
for x in (i for j in (range(30), range(2000, 5002)) for i in j):
pass
''', number=number)
print('generator expression:', t/number * 1000000, 'microsec/one execution')
In my opinion, the itertools.chain
is more readable. But what really is important...
itertools: 264.4522138986938 microsec/one execution
generator expression: 785.3081048010291 microsec/one execution
... it is about 3 times faster.