Convert negative index in Python to positive index

Viewed 3940

I'm trying to find a way to get the index of an item in a list in Python given its negative index, including an index of 0.

For example with a list, l of size 4:

l[0]  # index 0
l[-1] # index 3
l[-2] # index 2

I have tried using

index = negative + len(l)

however this will not work when the index is 0.

The only way I have found so far involves an if/else statement.

 index = 0 if negative == 0 else negative + len(l)

Is there a possible way to do this in Python without having to use an if statement?

I am trying to store the index of the item so I can access it later, but I am being given indices starting from 0 and moving backwards through the list, and would like to convert them from negative to positive.

4 Answers

index = index modulo size

index = index % len(list)

For a list of size 4, it will have following values for given indices :

 4 -> 0
 3 -> 3
 2 -> 2
 1 -> 1 
 0 -> 0
-1 -> 3
-2 -> 2
-3 -> 1
-4 -> 0

If you try to "go back" starting with a non-negative index, you can also use

index = len(l) - index - 1

to compute the "index from the back".

This is how you have to do it in many other programming languages. Pythons negative indices are just syntactic sugar.

But if you really use negative indices, this dirty hack is a one-liner without if and else:

index = int(negative != 0 and negative + len(l))

Explanation:

  • if negative == 0 the result of the and expression is False which is converted to 0 by calling int.
  • else the result of and is negative + len, see also here. The call to int then just does nothing.

This is good for learning Python, but I usually avoid such tricks. They are hard to read for you and others, and maybe you want to read your program in a few months again and you then you will wonder what this line is doing.

You can use the ~ complement operator. It will give you the inverse index as you require.

>>> l = ["a", "b", "c", "d"]
>>> l[0]
'a'
>>> l[~0]
'd'
>>> l[~3]
'a'
>>> l[~-1]
'a'
>>> l[-1]
'd'

A negative index is the same as subtracting from the length:

>> lst = [1, 2, 3]
>> lst[-1] == lst[len(lst) - 1]
True

So you could get an always positive value with a small if statement:

i = -2
index = i if number >= 0 else len(lst) - i 

In fact, you could use modulus to make an index wrap over back to 0 if the length is more than the length of the list:

# assuming length of list is 4
index = i % len(list)

# with i at 0:
0 % 4 == 0 # that works

# with i as -2
-2 % 4 == 2 # that works

# with i as 3:
3 % 4 == 3 % # that works
Related