2015-07-20 2 views
1

У меня есть список 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]

Есть ли более краткий или более эффективный способ осуществить это?

+0

Неясно, каков ваш желаемый результат. –

+0

Ваши элементы просто цифры? Или они могут быть другими объектами/типами? – Manhattan

ответ

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

Если вы хотите только пары (это не будет включать в себя 100, если 101 не находится в диапазоне) используют itertools.chain с range и zip (рассмотреть возможность использования xrange и 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] 
+1

Здесь следует отметить, что вы можете сделать это без распаковки, используя вместо этого 'itertools.chain.from_iterable'. +1, тем не менее. – Manhattan

+0

Упоминание 'izip' для пользователей Python 2. –

3

Используйте модуль с enumerate() для фильтрации по индексу.

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

Другой способ, с помощью zip

[i for t in zip(A[::10],A[1::10]) for i in t] 

Logic - Loop более двух элементов в списке, пропустив 10 сразу, но начиная с одного из них от 1, а другой от 0

Используя ту же логику, вы можете попробовать itertools.izip (для пользователей py2)

from itertools import izip 
[i for t in izip(A[::10],A[1::10]) for i in t] 

Timing -

  • 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 очень быстро здесь!

1

С Bhargav Рао взял 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] 

Опять же, замените range на xrange на Python 3 и просто используйте встроенный filter для Python 3.

Смежные вопросы