25

So I don't really get the deal with the stride parameter in slicing.
For example, "123456"[::-2] produces "642", but why does "123456"[1::-2] produce "2" and "123456"[2::-2] produce "31"?

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
user995788
  • 251
  • 1
  • 3
  • 4

6 Answers6

36

The easiest way to explain is probably to address your examples:

"123456"[::-2]
# This takes the whole string ([::])
# Then it works backward (-)
# and it does every other character (2)

"123456"[1::-2]
# This is also working backward (-)
# every other character (2)
# but starting at position 1, which is the number 2.

"123456"[2::-2]
# Again, working backward (-)
# Every other character (2)
# begin at position 2, so you end up with positions 2, and 0, or '31'

The slicing syntax is [<start>:<end>:step]. If <start> is omitted and the step is negative then it starts at the end of the string.

g.d.d.c
  • 46,865
  • 9
  • 101
  • 111
  • 2
    This is a very good answer, a clarification for the OP. `[::-2]` takes then whole string since you didn't assign a `start` so it will assume it's `0` much like `range(number)`. Also, try to get the hang of it playing with the indexes, once you do, it is a very powerful feature. For example, this is a cool one liner palindrome checker: `string == string[::-1]`. Good luck! – Trufa Oct 14 '11 at 16:54
  • For "123456"[::-2] why does it start with 6 but not 1? I thought by leaving out the variables in [::] by default it goes from the very beginning (ie. 1) to the end, so surely it should be 153...? – Constantly confused Sep 08 '18 at 10:28
  • @DanielMak - huh? It doesn't start at index 0 and then wrap back around. There's no way you'd get 153. – g.d.d.c Sep 09 '18 at 01:51
  • Yea that is what I don't understand...I mean under normal circumstances (eg not going backwards) by leaving out start and finish we start at charecter zero. Now the only thing we changed is by specifying it to go backwards: we still didn't change the stsrt and finish parameter, so why does it now start at 6 instead of 1? Sorry I am only a week old to the coding world but I am really grateful for your help! – Constantly confused Sep 09 '18 at 06:47
  • 2
    @DanielMak - That's just how the language is specified. If you omit the start, and the step is negative, then the input list (and the result) are reversed. There's some more reading available here: https://www.pythoncentral.io/how-to-slice-listsarrays-and-tuples-in-python/. There's not much more to say about it - it's just _how it works_. – g.d.d.c Sep 09 '18 at 16:12
6

Remember that indices start from zero. With this in mind, it may be clearer if you change your string to '012345':

In [1]: '012345'[1::-2]
Out[1]: '1'

In [2]: '012345'[2::-2]
Out[2]: '20'

In [3]: '012345'[5::-2]
Out[3]: '531'

As you can see, the slice does start from the correct index and does take the correct (negative) stride at each step until in reaches the beginning of the string.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
6

That's because the syntax is string[start:end:step]

"123456"[::-2]

Produces "642" because it'll start from the last character. This is because you didn't provide from which position the slice would be executed. So it'll go back by 2 characters from the last one until it reaches the first one.

"123456"[1::-2]

Produces "2" because you told Python to start from the 2nd character (index 1 from the string) and you told Python to go back 2 steps from that position. Which in this case, Python would obviously return just "2". This is because when Python tried to go back by 2 steps, it already hit the first character in the string with just one step.

"123456"[2::-2]

You should be able to figure this one out by now. But I'll just explain it anyway. So, you told Python to start from the third character (or index 2) and then go back 2 steps from there until it reaches the first character. So it'll start from "3" and then go back 2 steps, and accidentally the first character - which happens to be "1" - has been reached. So Python will give you "31"

Kemal Fadillah
  • 9,760
  • 3
  • 45
  • 63
0

lets understand about the slicing in python syntax:

string[starting index : ending index : step]

and your first example:

"123456"[::-2]

[::], without specifying any starting index, it will take the whole string, 123456

[::-2], the value -2 means start counting from end of the string with every 2 steps.

So, you will get 642.

Yong En
  • 1
  • 1
  • 2
0

The way I understand this is by asking myself what are the defaults for start, stop and step when they are not specified. Say we want to slice the string x="123456". We have

x[start:stop:step]

equivalent to

x[slice(start,stop,step)]

  1. When none is specified

slice is [::] that is equivalent to:

[0:len(x):1]

Stop being len(x) as we start index starts at 0.


  1. When step is negative

Let's say slice is this: [::-1]

equivalent to:

[-1: -(len(x) + 1) : -1]
=[-1: ~len(x): -1] #~ being the bitwise complement

Let's see if we can answer your questions based upon the defaults.


Case a

>>> "123456"[::-2]
"642"

Say

>>> x = "123456"
>>> x[::-2]
= [-1: -( len(x) + 1)  :-2]
= x[-1:-7:-2]
= x[-1] + x[-1 + -2] + x[-1 + -2 + -2]
= x[-1] + x[-3] + x[-5]
= "642"

Case b

>>> "123456"[1::-2]
"2"

Here are the steps to reproduce to get to the result:

>>> x[1::-2]
= x[1: -(len(x) + 1): -2]
= x[1:-7:-2]
= x[1] + x(two indices to the left of x[1])
= x[1] + "" = x[1]
= "2"

Case 3

Here is case 3:

>>> "123456"[2::-2]
"31"

Steps to reproduce:

>>> x[2::-2]
= x[2: -(len(x) + 1): -2]
= x[2:-7:-2]
= x[2] + x[2-2]
= x[2] + x[0]
= "31"
XxJames07-
  • 1,833
  • 1
  • 4
  • 17
0

When you're using stride it has basically two parameters. (index to start stride, stride interval)

"1234"[index::interval]

Just remember the stings are indexed starting at zero so

"123456"[2::-2]

is saying that start at index 2 or "3" and grab each within the interval.

"31"
stehlikio
  • 68
  • 5