Pythonic способ вернуть список каждого n-го элемента в больший список - PullRequest
141 голосов
/ 10 сентября 2009

Скажем, у нас есть список чисел от 0 до 1000. Есть ли эффективный способ составления списка первого и каждого последующего 10-го элемента, т. Е. [0, 10, 20, 30, ... ]?

Да, я могу сделать это, используя цикл for, но мне интересно, есть ли более аккуратный способ сделать это, возможно, даже в одной строке?

Ответы [ 9 ]

240 голосов
/ 10 сентября 2009
>>> l = range(165)
>>> l[0::10]
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]

РЕДАКТИРОВАТЬ: просто для удовольствия, небольшое сравнение времени (игнорируя граничное условие):

$ python -m timeit -s "l = range(1000)" "l1 = [x for x in l if x % 10 == 0]"
1000 loops, best of 3: 525 usec per loop
$ python -m timeit -s "l = range(1000)" "l1 = l[0::10]"
100000 loops, best of 3: 4.02 usec per loop
46 голосов
/ 10 сентября 2009
  1. source_list[::10] является наиболее очевидным, но это не работает для любого итерируемого и не эффективно для памяти больших списков.
  2. itertools.islice(source_sequence, 0, None, 10) работает для любой итерации и эффективна по мере, но, вероятно, не самое быстрое решение для большого списка и большого шага.
  3. (source_list[i] for i in xrange(0, len(source_list), 10))
23 голосов
/ 10 сентября 2009

Вы можете использовать оператор среза следующим образом:

l = [1,2,3,4,5]
l2 = l[::2] # get subsequent 2nd item
15 голосов
/ 10 сентября 2009

из руководства: s[i:j:k] slice of s from i to j with step k

li = range(100)
sub = li[0::10]

>>> sub
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
12 голосов
/ 10 сентября 2009
newlist = oldlist[::10]

Выбирает каждый 10-й элемент списка.

3 голосов
/ 10 сентября 2009

Почему бы просто не использовать step параметр range , а также для получения:

l = range(0, 1000, 10)

Для сравнения, на моей машине:

H:\>python -m timeit -s "l = range(1000)" "l1 = [x for x in l if x % 10 == 0]"
10000 loops, best of 3: 90.8 usec per loop
H:\>python -m timeit -s "l = range(1000)" "l1 = l[0::10]"
1000000 loops, best of 3: 0.861 usec per loop
H:\>python -m timeit -s "l = range(0, 1000, 10)"
100000000 loops, best of 3: 0.0172 usec per loop
2 голосов
/ 10 сентября 2009

Вот лучшая реализация понимания списка «каждый десятый элемент», в котором содержимое списка не используется как часть теста на членство:

>>> l = range(165)
>>> [ item for i,item in enumerate(l) if i%10==0 ]
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
>>> l = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
>>> [ item for i,item in enumerate(l) if i%10==0 ]
['A', 'K', 'U']

Но это все еще намного медленнее, чем просто использование списка.

2 голосов
/ 10 сентября 2009
existing_list = range(0, 1001)
filtered_list = [i for i in existing_list if i % 10 == 0]
0 голосов
/ 10 сентября 2009

Для этого созданы списки:

smaller_list = [x for x in range(100001) if x % 10 == 0]

Вы можете получить больше информации о них в официальной документации Python: http://docs.python.org/tutorial/datastructures.html#list-comprehensions

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...