251

Say we have a list of integers from 0 to 1000:

[0, 1, 2, 3, ..., 997, 998, 999]

How do I get a new list containing the first and every subsequent 10th item?

[0, 10, 20, 30, ..., 990]

I can do this using a for loop, but is there a neater way, perhaps even in one line of code?

9 Answers 9

411
>>> xs = list(range(165))
>>> xs[0::10]
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]

Note that this is around 100 times faster than looping and checking a modulus for each element:

$ python -m timeit -s "xs = list(range(1000))" "[x for i, x in enumerate(xs) if i % 10 == 0]"
500 loops, best of 5: 476 usec per loop

$ python -m timeit -s "xs = list(range(1000))" "xs[0::10]"
100000 loops, best of 5: 3.32 usec per loop
Sign up to request clarification or add additional context in comments.

7 Comments

Sure, list comprehensions are more powerful in general. OTOH, the question posits an existing list and, in that case, a slice works just fine.
I commented on this below in the list comprehension answers. Be careful with "if x % 10 == 0". It works only with this particular list example, but if the input list is for example l=range(0,1000,2) it won't pull out every 10th item.
@Andre: very true. So this is an example of a humble language feature, the slice operator, which turns out in this case (1) to make it easier to get the correct results; (2) results in a more concise expression; and (3) happens to be 2 orders of magnitude faster. (1) is by far the most important concern, of course, but, thanks to the careful design and implementation of the language, you get all three for the price of 1. Nice question and responses.
The 0 is redundant in l[0::10]. l[::10] is more readable, less confusing.
Your comparison is not appropriate because you are selecting every element that is divisible by 10 instead of selecting every 10th element. It will be more appropriate to compare slicing notation with this: lst = list(range(1000)); lst1 = [lst[i] for i in range(0, len(lst), 10)]. On my machine, I get "1000000 loops, best of 5: 395 nsec per loop" for slicing notation and "20000 loops, best of 5: 11.1 usec per loop" for list comprehension.
|
77
  1. source_list[::10] is the most obvious, but this doesn't work for any iterable and is not memory efficient for large lists.
  2. itertools.islice(source_sequence, 0, None, 10) works for any iterable and is memory-efficient, but probably is not the fastest solution for large list and big step.
  3. (source_list[i] for i in xrange(0, len(source_list), 10))

2 Comments

+1 Best answer, IMO. All three proposals a general solutions (ie. take the source list as a given). The generator solution (3.) is nice as it filters on the index of the source list. It's probably as memory efficient as 2. Both the indices and the result list are generators and thus constructed lazily, which is also probably the fastest if you don't need the result list in a single chunk. Only if the source list could be a generator I would go with Paul's "item, i in enumerate(l)" idiom, as there is no len() of a generator. BTW, which kind of iterable would not work with 1.? Generators?!
Iterable = object with __iter__() method returning iterator (object with next() method)
37

Use range(start, end, step)

li = list(range(0, 1000, 10))

[0, 10, 20, 30, 40, 50, 60, 70, 80, 90 ... 990]

Or, if you have a list use slice: From manual: s[i:j:k] slice of s from i to j with step k

yourlist = [0, ... ,10 ...]  
sub = yourlist[::10]  # same as yourlist[0:100:10]

>>> sub
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

Comments

34

You can use the slice operator like this:

l = [1,2,3,4,5]
l2 = l[::2] # get subsequent 2nd item

2 Comments

how to get every 2nd item starting from the 3rd?
@user1993 L[2::2]
14
newlist = oldlist[::10]

This picks out every 10th element of the list.

Comments

6

Why not just use a step parameter of range function as well to get:

l = range(0, 1000, 10)

For comparison, on my machine:

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

1 Comment

@SilentGhost: That's true, but as this is a beginner question the range function might be what they really want to do, so I think it's a valid answer. (Though the upper limit should be 1001, not 1000)
4
existing_list = range(0, 1001)
filtered_list = [i for i in existing_list if i % 10 == 0]

4 Comments

why do you have the if clause when range(0, 1001, 10) already only takes every 10th element?
Same comment here, this doesn't solve the more general problem of "Pythonic way to return list of every n’th item in a larger list" your solution depends on the fact that the example list's values are 0 to 1000 and only pulls items out of the list that has a value divisible by 10 instead of every 10th item.
Well, the OP writes: "we have a list of numbers from zero to 1000". So he doesn't have the need for a general solution.
He writes 'Say we have..' which implies its just an example. If he really wanted every 10th number out of a list of zero to 1000 then the answer would be range(0,1001,10) or something similar.
1

Here is a better implementation of an "every 10th item" list comprehension, that does not use the list contents as part of the membership test:

>>> 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']

But this is still far slower than just using list slicing.

Comments

-10

List comprehensions are exactly made for that:

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

You can get more info about them in the python official documentation: http://docs.python.org/tutorial/datastructures.html#list-comprehensions

2 Comments

The upper bound should be 1000, not 10000. Your solution does not include the upper bound of 1000 since range stops at 999. +1 for the link to list-comprehension.
This doesn't actually pull out every 10th item, it pulls out every item that has a value divisible by 10. In this particular example its the same thing, but it might not be.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.