每十个元素从列表中获取两个连续元素
Getting two consecutive elements from a list every ten elements
我有一个列表A
,我想获取元素 1、2、11、12、21、22 等作为列表。
比如A = range(100)
,那么我要[0, 1, 10, 11, 20, 21, ..., 90, 91]
现在我有[num for elem in [[A[i], A[i+1]] for i in range(0, len(A)-1, 10)] for num in elem]
是否有更简洁或更有效的实现方式?
如果你只想要对(如果 101 不在范围内,这将不包括 100)使用 itertools.chain
with range
and zip
(consider using xrange
and itertools.izip
以获得更大的 N
值:
itertools.chain(*zip(range(0, N, 10), range(1, N, 10)))
或者使用itertools.chain.from_iterable
避免解包:
itertools.chain.from_iterable(zip(range(0, N, 10), range(1, N, 10)))
查看内容:
>>> N = 100
>>> list(itertools.chain(*zip(range(0, N, 10), range(1, N, 10))))
[0, 1, 10, 11, 20, 21, 30, 31, 40, 41, 50, 51, 60, 61, 70, 71, 80, 81, 90, 91]
使用带 enumerate()
的取模运算符按索引过滤。
[elem for idx,elem in enumerate(A) if idx%10 in (0,1)]
怎么样:
[A[i] for i in xrange(0, len(A)) if i%10 in (0, 1)]
[elem for i, elem in enumerate(A) if i %10 in (0, 1)]
使用zip
的另一种方式
[i for t in zip(A[::10],A[1::10]) for i in t]
Logic - 通过一次跳过 10 个来遍历列表中的两个元素,但其中一个从 1 开始,另一个从 0
使用相同的逻辑,您可以尝试itertools.izip
(对于Py2用户)
from itertools import izip
[i for t in izip(A[::10],A[1::10]) for i in t]
时间 -
zip
$ python -m timeit -s "A = range(100)" "[i for t in zip(A[::10],A[1::10]) for i in t]"
100000 loops, best of 3: 1.98 usec per loop
izip
$ python -m timeit -s "A = range(100);from itertools import izip" "[i for t in izip(A[::10],A[1::10]) for i in t]"
1000000 loops, best of 3: 1.79 usec per loop
比较其他答案
$ python -m timeit -s "A = range(100)" "[elem for idx,elem in enumerate(A) if idx%10 in (0,1)]"
100000 loops, best of 3: 9.39 usec per loop
$ python -m timeit -s "A = range(100)" "[A[i] for i in xrange(0, len(A)) if i%10 in (0, 1)]"
100000 loops, best of 3: 7.92 usec per loop
izip
这里速度很快!
由于 Bhargav Rao 选择 obvious 压缩切片,这里有一个相当简单的协程来执行此操作,因为 filter
只需要两个 True
和八个 [=15] =] 的正确答案:
import itertools # only needed for Python 2
def first_two_of_ten():
x2, x8 = xrange(2), xrange(8) # use range in Python 3
yield # gotta queue up a coroutine to send to it
while True:
for i in x2:
yield True
for i in x8:
yield False
和用法:
ftot = first_two_of_ten()
next(ftot) # gotta queue the coroutine up
的实际使用情况
>>> list(itertools.ifilter(ftot.send, xrange(50)))
[0, 1, 10, 11, 20, 21, 30, 31, 40, 41]
同样,用 range
代替 Python 3 中的 xrange
,并且也只使用内置的 filter
代替 Python 3。
我有一个列表A
,我想获取元素 1、2、11、12、21、22 等作为列表。
比如A = range(100)
,那么我要[0, 1, 10, 11, 20, 21, ..., 90, 91]
现在我有[num for elem in [[A[i], A[i+1]] for i in range(0, len(A)-1, 10)] for num in elem]
是否有更简洁或更有效的实现方式?
如果你只想要对(如果 101 不在范围内,这将不包括 100)使用 itertools.chain
with range
and zip
(consider using xrange
and itertools.izip
以获得更大的 N
值:
itertools.chain(*zip(range(0, N, 10), range(1, N, 10)))
或者使用itertools.chain.from_iterable
避免解包:
itertools.chain.from_iterable(zip(range(0, N, 10), range(1, N, 10)))
查看内容:
>>> N = 100
>>> list(itertools.chain(*zip(range(0, N, 10), range(1, N, 10))))
[0, 1, 10, 11, 20, 21, 30, 31, 40, 41, 50, 51, 60, 61, 70, 71, 80, 81, 90, 91]
使用带 enumerate()
的取模运算符按索引过滤。
[elem for idx,elem in enumerate(A) if idx%10 in (0,1)]
怎么样:
[A[i] for i in xrange(0, len(A)) if i%10 in (0, 1)]
[elem for i, elem in enumerate(A) if i %10 in (0, 1)]
使用zip
[i for t in zip(A[::10],A[1::10]) for i in t]
Logic - 通过一次跳过 10 个来遍历列表中的两个元素,但其中一个从 1 开始,另一个从 0
使用相同的逻辑,您可以尝试itertools.izip
(对于Py2用户)
from itertools import izip
[i for t in izip(A[::10],A[1::10]) for i in t]
时间 -
zip
$ python -m timeit -s "A = range(100)" "[i for t in zip(A[::10],A[1::10]) for i in t]" 100000 loops, best of 3: 1.98 usec per loop
izip
$ python -m timeit -s "A = range(100);from itertools import izip" "[i for t in izip(A[::10],A[1::10]) for i in t]" 1000000 loops, best of 3: 1.79 usec per loop
比较其他答案
$ python -m timeit -s "A = range(100)" "[elem for idx,elem in enumerate(A) if idx%10 in (0,1)]"
100000 loops, best of 3: 9.39 usec per loop
$ python -m timeit -s "A = range(100)" "[A[i] for i in xrange(0, len(A)) if i%10 in (0, 1)]"
100000 loops, best of 3: 7.92 usec per loop
izip
这里速度很快!
由于 Bhargav Rao 选择 obvious 压缩切片,这里有一个相当简单的协程来执行此操作,因为 filter
只需要两个 True
和八个 [=15] =] 的正确答案:
import itertools # only needed for Python 2
def first_two_of_ten():
x2, x8 = xrange(2), xrange(8) # use range in Python 3
yield # gotta queue up a coroutine to send to it
while True:
for i in x2:
yield True
for i in x8:
yield False
和用法:
ftot = first_two_of_ten()
next(ftot) # gotta queue the coroutine up
的实际使用情况
>>> list(itertools.ifilter(ftot.send, xrange(50)))
[0, 1, 10, 11, 20, 21, 30, 31, 40, 41]
同样,用 range
代替 Python 3 中的 xrange
,并且也只使用内置的 filter
代替 Python 3。