Reputation: 143112
Maybe someone can explain why a particular slice operation to reverse a string doesn't work. There must be something about slices I don't understand. Basic operation: s[start:end:step]
Given
s='abcd'
to reverse this string I can do using default values
s[::-1]
or
s[-1::-1]
Those are fine, but why doesn't
s[-1:-1:-1]
work and give me the whole string reversed? It should start at with the last character in the string at (-1), and the stepsize is -1. It should run down to one before -1 i.e., index 0. Instead I get ''.
for i in xrange(3, -2, -1):
print 's[-1:%d:-1] => ' %i,
print s[-1:i:-1]
yields:
s[-1:3:-1] => # didn't expect any output
s[-1:2:-1] => d
s[-1:1:-1] => dc
s[-1:0:-1] => dcb
s[-1:-1:-1] => # shouldn't this be 'dcba'?
what am I missing here?
(I did see a lot of posting on reversing strings, but if this particular item was explained somewhere I missed it)
Upvotes: 3
Views: 776
Reputation: 308402
That's kind of unfortunate, isn't it? Here's an awkward workaround.
for i in range(3, -2, -1):
j = i if i != -1 else None
print 's[-1:%s:-1] => ' % str(j),
print s[-1:j:-1]
s[-1:3:-1] =>
s[-1:2:-1] => d
s[-1:1:-1] => dc
s[-1:0:-1] => dcb
s[-1:None:-1] => dcba
Here's a variation on the same thing. I'm not sure if it's any less awkward.
for i in range(3, -1, -1) + [None]:
print 's[-1:%s:-1] => ' % str(i),
print s[-1:i:-1]
s[-1:3:-1] =>
s[-1:2:-1] => d
s[-1:1:-1] => dc
s[-1:0:-1] => dcb
s[-1:None:-1] => dcba
Upvotes: 1
Reputation: 151077
You can't expect -1
to mean both the final item in the string and the "item before" the first item in the string. That would be inconsistent.
Perhaps you're imagining that Python is treating a string as a loop, and thinking of -1
as if it were simultaneously the "item before" 0
and the last item in the string. But that's not the case. For example, if that were the case, then this would hold:
'abcd'[-2:-1:-1] == 'cbad'
But it doesn't. The result is simply the empty string.
>>> 'abcd'[-2:-1:-1]
''
The correct interpretation of negative indices in string slicing is as reverse indexing from the end of the string, not as cyclical indexing from 0
.
As further food for thought, consider the following:
a = 'abcd'
a[-1:-(len(a) + 0):-1] == 'dcb'
a[-1:-(len(a) + 1):-1] == 'dcba'
a[-1:-(len(a) + 2):-1] == 'dcba'
Upvotes: 1
Reputation: 500693
In this context, negative and non-negative indices are two separate classes:
It seems pretty logical to me that slicing is defined such that the latter never overflow into the former, as you seem to be expecting when you say:
It should run down to one before -1 i.e., index 0
Upvotes: 3
Reputation: 63757
You have missed the whole point of slicing
[start:end:stride]
is what a slice operator would look like
if stride is negative, then definitely your start should be greater than end as you are moving from high to low. All your examples which fails violates that.
You should definitely start reading Extended Slicing
Upvotes: 1
Reputation: 18653
s[-1:-1:-1]
Doesn't work for the same reason that
s[0:0]
doesn't give you 'abcd'.
When you slice, you are referring to the space between two elements, not the location of those elements. So you're asking for the space between -1 and -1, which is ''.
Upvotes: 6
Reputation: 133634
In
>>> s[-1:-1:-1]
>>> ''
The start
and end
are both -1
so they are the same. A slice takes each element in the array from the start
to the end
as it increases by the step
each time. If it has already reached the end
then the slice is finished... therefore it returns ''
.
Try:
>>> s[1:1:1]
>>> ''
That might help this make more sense as it is almost the same thing, but positive.
Upvotes: 3