5

https://stackoverflow.com/a/9868665/433570 finds the first item.

I can think of doing reverse first before applying the solution above. But then I would end up with two reverse which might be avoided.

Is there a better solution than using two reverse and next ?

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
eugene
  • 39,839
  • 68
  • 255
  • 489

3 Answers3

11

Instead of reversing the list, which may be a lengthy operation (l.reverse()) because it reverses the whole list, I'd simply use a reversed iterator reversed(l) with whatever matching method you want, since you can stop early at the first match, it may save you time vs reversing the whole list.

Of course there's best case and worst cases for both methods, below may give you an idea, based on where the match is in the list (e.g. towards the end, the beginning, or the middle)

In [1]: l = range(0, 100000)

In [2]: %timeit next((i for i in reversed(l) if i == 1), None)
100 loops, best of 3: 2.94 ms per loop

In [3]: %timeit next((i for i in reversed(l) if i == 50000), None)
1000 loops, best of 3: 1.39 ms per loop

In [4]: %timeit next((i for i in reversed(l) if i == 99000), None)
10000 loops, best of 3: 29.4 µs per loop

Below is an idea of how long it takes to reverse the same list:

In [5]: %timeit l.reverse()
10000 loops, best of 3: 71.5 µs per loop

Note: I ran above on Python 2, so range() is a list not an iterator, so no need to list(range()) it to make the comparison worthwhile.

bakkal
  • 54,350
  • 12
  • 131
  • 107
3

The accepted answer in related questions suggested to use an iterator on the list to build a generator containing only matching elements and take first element from that generator:

next(obj for obj in objs if condition)

You can do the same using range in opposite order:

next(objs[i] for i in range(len(objs) -1, -1, -1))

(use xrange in Python2)

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
0
x = range(11)
y = next((i for i in reversed(x) if i % 2 == 1), None)
eddiewould
  • 1,555
  • 16
  • 36