0

I have searched for a similar topic, as I assume someone must have come across this problem before. Any links to relevant topics are appreciated :)

I want to delete all values past (and including) the last index of "x".

Given the list: a = [0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]

Do something, e.g. del a[a.rindex(2):]

And end up with a == [0, 1, 2, 3, 4, 5, 0, 1] - Note that the 2 is deleted

DarkMatterMatt
  • 576
  • 10
  • 22

4 Answers4

2

There is no rindex in Python and index returns the index of the first occurrence.

Using len(a) - a[::-1].index(2) (the first occurrence from the end is the last occurrence) will return the index of the last occurrence of 2 so we can use slicing:

li = [0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]
element = 2
last_index = len(li) - li[::-1].index(element)
li = li[:last_index - 1]
print(li)
# [0, 1, 2, 3, 4, 5, 0, 1]

Note that this approach isn't the best in the performance department since it needs to create a list in memory and then reverse it.

DeepSpace
  • 78,697
  • 11
  • 109
  • 154
2
def last_index(a,target):
    for i in a:
        check = a[-1]
        a.pop()
        if check == target :
            break
    return a

EDIT Thanks to the comments, this can be made more simple like this :

def last_index(a,target):
    while a.pop() != target : pass
    return a
Mike
  • 121
  • 9
  • Very nice. Just a small suggestion: `for _ in a:` would be more pythonic: 1. Unused variables in loops are usually called `_`, 2. No need to create a new `range` object (in Python 3) or a new list (in Python 2) which is what `range(len(a))` does. – DeepSpace May 22 '17 at 07:33
  • 2
    The function name `last_index` suggests that it will just return the index, while it's actually also modifying the original list. – ChatterOne May 22 '17 at 07:39
  • I ended up using this, but not as a function. It was `for _ in a:` | `a.pop()` | `if a[-1] == 0:` | `break`, where the |s are line breaks – DarkMatterMatt May 22 '17 at 07:43
  • @DeepSpace Thanks, I'm also on my way to make my codes more pythonic, and your comments really helped me out! I usually use len(range(list)) when I need index of the current item, but this is not necessary for this case I guess. – Mike May 22 '17 at 07:51
  • @Mike @DeepSpace, you could combine the `a.pop(); check = a[-1]` couldn't you? `check = a.pop() ; while check != target: ; check = a.pop()` That deletes the target as well. – DarkMatterMatt May 22 '17 at 07:59
  • @DarkMatterMatt Correct, `pop` returns the removed object. – DeepSpace May 22 '17 at 08:00
  • even shorter: `while a.pop() != target: pass` – DarkMatterMatt May 22 '17 at 08:02
2
a = [1,2,4,2,3,4,5,2,3]

def delete_last_index(list,n):
  index = len(a) - 1 - a[::-1].index(n)
  return list[:index]

a = delete_last_index(a,2)
print(a)

This should give: [1, 2, 4, 2, 3, 4, 5]

1

I've managed to so something you might want:

>>> a = [0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]
>>> last = len(a) - a[::-1].index(2) - 1
>>> last
8
>>> a[:last]
[0, 1, 2, 3, 4, 5, 0, 1]

based on this question.

EDIT

Alternatively if saving memory is an issue, you can iterate over the list and pop element by element. This will be more time-consuming, but less memory-consuming.

>>> a = [0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]
>>> a
[0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]
>>> while a[-1] != 2:
...   a.pop()
... 
5
4
3
>>> a
[0, 1, 2, 3, 4, 5, 0, 1, 2]
>>> a.pop()
2
>>> a
[0, 1, 2, 3, 4, 5, 0, 1]
Community
  • 1
  • 1
gonczor
  • 3,994
  • 1
  • 21
  • 46