每十个元素从列表中获取两个连续元素

时间:2015-07-20 01:47:27

标签: python list list-comprehension

我有一个列表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]

是否有更简洁或更有效的方法来实现它?

6 个答案:

答案 0 :(得分:3)

如果您只想要配对(如果101不在范围内,则不包括100)请使用itertools.chainrange以及zip(考虑使用xrange和{ {3}}更大的N}值:

itertools.chain(*zip(range(0, N, 10), range(1, N, 10)))

或者使用itertools.izip避免解包:

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]

答案 1 :(得分:3)

使用带enumerate()的模数运算符来过滤索引。

[elem for idx,elem in enumerate(A) if idx%10 in (0,1)]

答案 2 :(得分:3)

怎么样:

[A[i] for i in xrange(0, len(A)) if i%10 in (0, 1)]

答案 3 :(得分:3)

[elem for i, elem in enumerate(A) if i %10 in (0, 1)]

答案 4 :(得分:3)

使用zip

的另一种方法
[i for t in zip(A[::10],A[1::10]) for i in t]

逻辑 - 通过一次跳过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在这里非常快!

答案 5 :(得分:1)

由于Bhargav Rao采用obvious选择的压缩切片,所以这是一个相当简单的协程,因为filter只需要两个True和八个False要做到这一点:

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

以及itertools.ifilter

的实际使用情况
>>> list(itertools.ifilter(ftot.send, xrange(50)))
[0, 1, 10, 11, 20, 21, 30, 31, 40, 41]

再次,在Python 3中将range替换为xrange,并且只使用内置的filter用于Python 3。