-1

Suppose I have the following list: a = [10, 8, 7, 5, 4, 4, 4, 2, 1, 1, 1]. Suppose I want to find the index of the last entry >= some threshold e.g. threshold = 4.

I have written the following code:

a = [10, 8, 7, 5, 4, 4, 4, 2, 1, 1, 1]
threshold = 4

last_index = len(a) - a[::-1].index(threshold) - 1

While this works, it is not very readable - is there a better way of writing this?

hslin
  • 51
  • 5

4 Answers4

1

There is sort of an idiom to find the last in any iterable:

*_, last_i = (i for i, v in enumerate(a) if v >= 4)

This of course is more helpful for iterators than for sequences that can be just searched efficiently from the back. The no extra space variant:

last_i = some_default
for i, v in enumerate(a):
    if v >= 4:
        last_i = i

You can do it from the back in a space efficent manner using next:

last_i = next(i for i in range(len(a)-1, -1, -1) if a[i] >= 4)
user2390182
  • 72,016
  • 6
  • 67
  • 89
  • Maybe the downvote is because of the creation of an extra list, but for not too much data (or iterators) I really like this approach. – Matthias Jul 07 '23 at 13:09
  • 1
    The extra list is contained in `_`. Do a `print(type(_))` and you'll see. – Matthias Jul 07 '23 at 13:10
  • =) oh true, what a blind spot! That is indeed a downside. – user2390182 Jul 07 '23 at 13:11
  • 1
    This could be one of the cases where the so called unpythonic approach with accessing elements with an index might be the better solution. Edit: ... until you came up with the `enumerate` version that even works if the data is not sorted :) – Matthias Jul 07 '23 at 13:13
  • Yeah, defo. As stated, this is more helpful for iterators. – user2390182 Jul 07 '23 at 13:14
  • This looks nice. – hslin Jul 07 '23 at 14:03
  • Thx, note however that this is not optimal algrithmically. Looking for the index from the back is more efficient. Even your own suggestion is probably faster and better despite the spurious extra list created by the slice. – user2390182 Jul 07 '23 at 14:18
  • `max()` rather than tuple unpacking: `last_i = max(i for i, v in enumerate(a) if v >= 4)` – Steven Rumbalski Jul 07 '23 at 18:01
  • @StevenRumbalski True, that woud work neatly in this case. Didn't even occur to me =) Leaving it as is tho, which is more generally applicable. Kinda coincidental to dealing with indexes that last means max, too. – user2390182 Jul 07 '23 at 21:14
0

is this a better method in your opinion ?

def last_entry(list, value):
    for i in range(len(a)-1, 0, -1):
        if a[i] >= value:
            print(i)
            break

a = [10, 8, 7, 5, 4, 4, 4, 2, 1, 1, 1]
threshold = 4
last_entry(a, threshold)
m4lou
  • 47
  • 1
  • 10
0

Try this

a = [10, 8, 7, 5, 4, 4, 4, 2, 1, 1, 1]
threshold = 4

last_index = None

for i in range(len(a) - 1, -1, -1):  # Iterate from last index to first index in reverse order
    if a[i] >= threshold:  # Check if the element satisfies the threshold condition
        last_index = i  # Store the last index if condition is met
        break  # Exit the loop after finding the last occurrence

if last_index is not None:
    print("Last index:", last_index)
else:
    print("Item not found.")

Output

Last index: 6
codester_09
  • 5,622
  • 2
  • 5
  • 27
0

You could use max on the indexes filtered on the condition:

last_index = max(i for i,n in enumerate(a) if n>=4)
Alain T.
  • 40,517
  • 4
  • 31
  • 51