0

I've got this piece of code that modifies a list based on a condition:

lst = [0, 0, 0, 2, 1]

for i, x in enumerate(reversed(lst)):
    if x == 0:
        lst[-i-1] = 9
        break

Is there a way I can do this in a better, more optimised way and without a while loop?

user270199
  • 905
  • 1
  • 6
  • 12
  • Do you have to use a list? Or can you use a numpy array? – alwaysmvp45 Aug 23 '20 at 22:50
  • @alwaysmvp45. Only a list. – user270199 Aug 23 '20 at 22:52
  • Does the list only include a sequence of 0's at the start or can they occur anywhere in the list? – Nick Aug 23 '20 at 23:05
  • @Nick: The list does indeed always start with a sequence of 0's. The only non-zero elements are at the end. Basically I need to replace the first 0 (counting from the end) with a 9. – user270199 Aug 23 '20 at 23:07
  • 2
    The question is indeed a duplicate if it's just looking for the last item meeting some criterion in a sequence - do note that your original solution is faster than either solutions proposed in the answers. – Grismar Aug 24 '20 at 00:21

2 Answers2

1

It appears you just want the starting lst modified by replacing the first element from the end that's a 0 with a 9.

How about this:

lst = [0, 0, 0, 2, 1]
lst[-(list(reversed(lst)).index(0)+1)] = 9

Sadly, you need the list() in there to have the .index(), since the result from reversed() (a list_reverseiterator) doesn't have that method.

Or if you're all about brevity:

lst[-lst[::-1].index(0)-1] = 9

I don't think that helps readability though. (Edit: removed initial -1::-1, the first -1 is superfluous as @Nick correctly pointed out)

Grismar
  • 27,561
  • 4
  • 31
  • 54
1

If the list starts with a sequence of 0's, and there are no other 0's in it, you can use list.count to find the position of the final 0 (it will be one less than the count of 0's in the list) and replace it with 9:

lst = [0, 0, 0, 2, 1]

lst[lst.count(0)-1] = 9
print(lst)

Output:

[0, 0, 9, 2, 1]
Nick
  • 138,499
  • 22
  • 57
  • 95
  • This only works if the input list always starts with nothing but zeroes - what should happen if the starting list is `lst = [1, 0, 0, 2, 1]`? – Grismar Aug 24 '20 at 00:07
  • @Grismar I asked that specific question of OP in the comments, and they said the only non-zero elements are at the end. – Nick Aug 24 '20 at 00:08
  • 1
    Ah you're right - in that case the solution works just fine; preferring an approach looking from the end or from the start would then only depend on the number of zeroes vs. the rest of the list. – Grismar Aug 24 '20 at 00:10
  • @Grismar yes, this has the penalty of searching the entire list, but it doesn't need to reverse it. And when there is only one zero, both methods have to search the entire list. – Nick Aug 24 '20 at 00:12
  • @Nick thanks for your answer. Taking into consideration Grismar's note,I would have thought that your solution would be faster than my own one where I loop through each element starting from the end of the list. Is .count() significantly slower than doing a loop? – user270199 Aug 24 '20 at 09:03
  • @user270199 I ran all 3 approaches through `timeit` (https://rextester.com/YNWJ34389); my approach was about 2x faster than @Grismar and 3-4x faster than yours. – Nick Aug 24 '20 at 09:30