91

Or, a more general question would be, how to slice an array to get every n-th line, so for even/odd you'd want to skip one line, but in the general case you'd want to get every n-th lines, skipping n-1 lines.

fatcat
  • 913
  • 1
  • 6
  • 4
  • 1
    i realize i can do it in a loop with it but i was wondering if i could just do it in one line instead – fatcat Feb 14 '11 at 00:58

4 Answers4

199

Assuming you are talking about a list, you specify the step in the slice (and start index). The syntax is list[start:end:step].

You probably know the normal list access to get an item, e.g. l[2] to get the third item. Giving two numbers and a colon in between, you can specify a range that you want to get from the list. The return value is another list. E.g. l[2:5] gives you the third to sixth item. You can also pass an optional third number, which specifies the step size. The default step size is one, which just means take every item (between start and end index).

Example:

>>> l = range(10)
>>> l[::2]         # even  - start at the beginning at take every second item
[0, 2, 4, 6, 8]
>>> l[1::2]        # odd - start at second item and take every second item
[1, 3, 5, 7, 9]

See lists in the Python tutorial.

If you want to get every n-th element of a list (i.e. excluding the first element), you would have to slice like l[(n-1)::n].

Example:

>>> l = range(20)
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

Now, getting every third element would be:

>>> l[2::3]
[2, 5, 8, 11, 14, 17]

If you want to include the first element, you just do l[::n].

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • I've never seen that before. The first number is the initial index and the last is the step then? Does anything go between the `::`? Or are both of them an operator, which is different from `:`? If I do `l[::1]` I get the original array then? – fatcat Feb 14 '11 at 01:00
  • 1
    @fatcat - http://docs.python.org/library/stdtypes.html#sequence-types-str-unicode-list-tuple-bytearray-buffer-xrange, see notes 3 & 5 – Jeremy Brown Feb 14 '11 at 01:01
  • @fatcat: Yes you would get the original array. I'd say more often you see just a slice from a start to an end index, like `l[2:5]`. The step is optional. – Felix Kling Feb 14 '11 at 01:03
1

This is more for me as a complete example ;)

>>> import itertools
>>> ret = [[1,2], [3,4,5,6], [7], [8,9]]
>>> itertools.izip_longest(*ret)
>>> [x for x in itertools.chain.from_iterable(tmp) if x is not None]
[1, 3, 7, 8, 2, 4, 9, 5, 6]
delijati
  • 411
  • 5
  • 14
1

example for indices 0,2,4... of myArr

myArr[list(range(0,len(myArr),2))]

example for indices 1,3,5... of myArr

myArr[list(range(1,len(myArr)+1,2))]

you can manipulate it anyway you want with the step parameter, in this case it is equal to 2. hope this helped

-1
> map(lambda index: arr[index],filter(lambda x: x%n == 0,range(len(arr))))

where arr is a list, and n slices are required.

ajmartin
  • 2,379
  • 2
  • 26
  • 42
  • 1
    -1 for using `map()` and `filter()` with a `lambda`. This is discouraged/slow and should **always** be done using a list comprehension. – ThiefMaster Sep 01 '13 at 12:25
  • 1
    Are there any experiments to back this claim? – ajmartin Sep 01 '13 at 22:29
  • 1
    I think there's a post from guido van rossum somewhere in the python mailing list archives about it. Anyway, it's kind of obvious since it's function call vs. no function call. Unless you are using Stackless calling functions is rather expensive – ThiefMaster Sep 01 '13 at 23:12