连接两个范围函数结果

时间:2012-12-31 09:34:12

标签: python python-3.x range concatenation

范围功能是否允许连接?就像我想制作一个range(30)&将其与range(2000, 5002)连接起来。所以我的连接范围是0, 1, 2, ... 29, 2000, 2001, ... 5001

这样的代码不适用于我最新的python(版本:3.3.0)

range(30) + range(2000, 5002)

8 个答案:

答案 0 :(得分:55)

您可以使用itertools.chain

from itertools import chain
concatenated = chain(range(30), range(2000, 5002))
for i in concatenated:
     ...

适用于任意迭代。请注意,你应该知道的Python 2和3之间range()的行为存在差异:在Python 2 range中返回一个列表,而在Python3中则是一个内存效率高的迭代器,但不是总是可取的。

列表可以与+连接,迭代器不能连接。

答案 1 :(得分:33)

可以使用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]

适用于您的请求,但这是一个很长的答案,所以我不会在这里发布。

注意:可以制作成发电机以提高性能:

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

甚至是生成器变量。

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

答案 2 :(得分:31)

我喜欢最简单的解决方案(包括效率)。解决方案是否如此并不总是很清楚。无论如何,Python 3中的range()是一个生成器。您可以将其包装到任何进行迭代的构造中。 list()能够从任何可迭代构造列表值。列表的+运算符进行连接。我在示例中使用较小的值:

>>> 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]

这是range(5) + range(10, 20)在Python 2.5中的确切行为 - 因为range()返回了一个列表。

在Python 3中,只有在您真正想构建列表时才有用。否则,我建议使用Lev Levitsky's itertools.chain解决方案。该文档还显示了非常简单的实现:

def chain(*iterables):
    # chain('ABC', 'DEF') --> A B C D E F
    for it in iterables:
        for element in it:
            yield element

Inbar Rose的解决方案很好,功能相同。无论如何,我的+1给Lev Levitsky和他关于使用标准库的论点。来自 Python的禅宗 ......

  

面对模棱两可,拒绝猜测的诱惑。

#!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')

在我看来,itertools.chain更具可读性。但真正重要的是......

itertools: 264.4522138986938 microsec/one execution
generator expression: 785.3081048010291 microsec/one execution

......它快了大约3倍。

答案 3 :(得分:5)

在extend方法的帮助下,我们可以连接两个列表。

>>> 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]

答案 4 :(得分:4)

Python 2.x中的

range()返回一个列表:

>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Python 2.x中的

xrange()返回一个迭代器:

>>> xrange(10)
xrange(10)

在Python 3 range()中也返回一个迭代器:

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

很明显,你不能像其他人指出的那样使用chain()来连接其他迭代器。

答案 5 :(得分:4)

在python3.5 +上,您可以在列表中使用可迭代的解压缩功能(请参阅PEP 448:Additional Unpacking Generalizations)。

如果您需要列表,

[*range(2, 5), *range(3, 7)]
# [2, 3, 4, 3, 4, 5, 6]

这将保留顺序,并且不会删除重复项。或者,您可能想要一个元组

(*range(2, 5), *range(3, 7))
# (2, 3, 4, 3, 4, 5, 6)

...或一组,

{*range(2, 5), *range(3, 7)}
# {2, 3, 4, 5, 6}

它也比调用chain更快。

%timeit list(chain(range(10000), range(5000, 20000)))
%timeit [*range(10000), *range(5000, 20000)]

738 µs ± 10.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
665 µs ± 13.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

不过,chain的好处是您可以传递任意范围的列表。

r = [range(2, 5), range(3, 7), ...]
flat = list(chain.from_iterable(r))

OTOH,尚未将拆包概括概括为任意序列,因此您仍然需要自己拆包各个范围。

答案 6 :(得分:0)

我遇到了这个问题,因为我试图连接未知数量的范围,这可能会重叠,并且不希望在最终迭代器中重复值。我的解决方案是使用setunion运算符,如下所示:

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

答案 7 :(得分:0)

您可以使用范围范围内的列表功能来创建列表 像这样

list(range(3,7))+list(range(2,9))