Concatenating two range function results

2019-01-22 06:00发布

问题:

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)

回答1:

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.



回答2:

Can be done using list-comprehension.

>>> [i for j in (range(10), range(15, 20)) for i in j]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 17, 18, 19]

Works for your request, but it is a long answer so I will not post it here.

note: can be made into a generator for increased performance:

for x in (i for j in (range(30), range(2000, 5002)) for i in j):
    # code

or even into a generator variable.

gen = (i for j in (range(30), range(2000, 5002)) for i in j)
for x in gen:
    # code


回答3:

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.



回答4:

With the help of the extend method, we can concatenate two lists.

>>> a = list(range(1,10))
>>> a.extend(range(100,105))
>>> a  
[1, 2, 3, 4, 5, 6, 7, 8, 9, 100, 101, 102, 103, 104]


回答5:

range() in Python 2.x returns a list:

>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

xrange() in Python 2.x returns an iterator:

>>> xrange(10)
xrange(10)

And in Python 3 range() also returns an iterator:

>>> r = range(10)
>>> iterator = r.__iter__()
>>> iterator.__next__()
0
>>> iterator.__next__()
1
>>> iterator.__next__()
2

So it is clear that you can not concatenate iterators other by using chain() as the other guy pointed out.



回答6:

I came to this question because I was trying to concatenate an unknown number of ranges, that might overlap, and didn't want repeated values in the final iterator. My solution was to use set and the union operator like so:

range1 = range(1,4)
range2 = range(2,6)
concatenated = set.union(set(range1), set(range2)
for i in concatenated:
    print(i)


回答7:

I know this is a bit old thread, but for me, the following works.

>>> for i in range(30) + range(2000, 5002):
...    print i

So does this

>>> for i in range(30) , range(2000, 5002):
...  print i

Of course the print output is different in the 2nd from the 1st.

Edit: I missed the follow-up comment form the OP stating python 3. This is in my python 2 environment.