范围功能是否允许连接?就像我想制作一个range(30)
&将其与range(2000, 5002)
连接起来。所以我的连接范围是0, 1, 2, ... 29, 2000, 2001, ... 5001
这样的代码不适用于我最新的python(版本:3.3.0)
range(30) + range(2000, 5002)
答案 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)
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)
我遇到了这个问题,因为我试图连接未知数量的范围,这可能会重叠,并且不希望在最终迭代器中重复值。我的解决方案是使用set
和union
运算符,如下所示:
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))