434,572 Members | 963 Online
Need help? Post your question and get tips & solutions from a community of 434,572 IT Pros & Developers. It's quick & easy.

Indentifying the LAST occurrence of an item in a list

 P: n/a For any list x, x.index(item) returns the index of the FIRST occurrence of the item in x. Is there a simple way to identify the LAST occurrence of an item in a list? My solution feels complex - reverse the list, look for the first occurence of the item in the reversed list, and then subtract its index from the length of the list - 1, i.e. LastOcc = len(x) - 1 - x[::-1].index(item) Is there a simpler solution? Thanks in advance Thomas Philips Apr 4 '07 #1
10 Replies

 P: n/a

 P: n/a On Apr 4, 10:55 am, "Terry Reedy"

 P: n/a On Apr 4, 11:20 am, "7stud"

 P: n/a "7stud"

 P: n/a Terry Reedy: def rindex(lis, item): for i in range(len(lis)-1, -1, -1): if item == lis[i]: return i else: raise ValueError("rindex(lis, item): item not in lis") This is an alternative, I don't know if it's faster: def rindex(seq, item): for pos, el in enumerate(reversed(seq)): if item == el: return len(seq) - 1 - pos else: raise ValueError("rindex(lis, item): item not in lis") t = [0, 1, 2, 3, 0] print rindex(t, 0) print rindex(t, 3) print rindex(t, 1) Bye, bearophile Apr 4 '07 #6

 P: n/a On Apr 5, 1:58 am, tkp...@hotmail.com wrote: For any list x, x.index(item) returns the index of the FIRST occurrence of the item in x. Is there a simple way to identify the LAST occurrence of an item in a list? My solution feels complex - reverse the list, look for the first occurence of the item in the reversed list, and then subtract its index from the length of the list - 1, i.e. LastOcc = len(x) - 1 - x[::-1].index(item) Is there a simpler solution? If you need to do this for several possible items in the same list, it may be worthwhile to build a dictionary containing all the answers: | >>seq = ['foo', 'bar', 'foo', 'bar', 'zot', 'foo'] | >>rindex = dict((elt, inx) for inx, elt in enumerate(seq)) | >>rindex | {'zot': 4, 'foo': 5, 'bar': 3} If you tell us what is the higher-level problem, we may be able to help you further. In other words, if lists did have a rindex method, what would you be using it to do? Are you constrained to use a list, or would another data structure be better? HTH, John Apr 4 '07 #7

 P: n/a Not sure below is better but it hacks at larger chunks (excuse the 10 second coding) m = [2,9,1,5,6,3,1,1,9,2] f = 1 temp = m location = m.index(f) gloc = location temp = m[location:] while 1: print(temp) try: location = temp.index(f) + 1 gloc += location except: break temp = temp[location:] #Remove the last 0th element gloc -= 1 print("Last location = %d" % gloc) Apr 5 '07 #8

 P: n/a On Apr 6, 4:55 am, "mkPyVS" >help(list.index) Help on method_descriptor: index(...) L.index(value, [start, [stop]]) -integer -- return first index of value I look forward to your next version. Cheers, John Apr 6 '07 #9

 P: n/a On Apr 5, 6:37 pm, "John Machin" >help(list.index) Help on method_descriptor: index(...) L.index(value, [start, [stop]]) -integer -- return first index of value I look forward to your next version. Great point! I was assuming the temp variable space was static but the pointer to the start of the list was moving-shame on me (what language is this now ;)! Couldn't resist the temptation to just collect all of the locations as I traversed m = [2,9,1,5,6,3,1,1,9,2] f = 1 #What we're looking for location = 0 #Start at beginning of list fIndexs = [] while 1: try: location = m.index(f,location) + 1 fIndexs.append(location-1) except ValueError: break print("Last location = %d" % fIndexs[-1]) print("All Items = %s" % fIndexs) Apr 6 '07 #10

 P: n/a On Apr 7, 9:25 am, "mkPyVS" help(list.index) Help on method_descriptor: index(...) L.index(value, [start, [stop]]) -integer -- return first index of value I look forward to your next version. Great point! I was assuming the temp variable space was static but the pointer to the start of the list was moving-shame on me (what language is this now ;)! Indeed. IMHO every function/method that searches a sequence should have start/stop arguments so that the caller can search a slice without actually copying the slice. > Couldn't resist the temptation to just collect all of the locations as I traversed m = [2,9,1,5,6,3,1,1,9,2] f = 1 #What we're looking for location = 0 #Start at beginning of list fIndexs = [] while 1: try: location = m.index(f,location) + 1 fIndexs.append(location-1) except ValueError: break print("Last location = %d" % fIndexs[-1]) 1. print is a statement, not a function. 2. fIndexs[-1] will crash and burn if there are no occurrences of f in m. print("All Items = %s" % fIndexs) FWIW, here's my take on a function that emulates the "missing" rindex method: 8<--- start rindex.py --- def rindex(seq, value, lo=0, hi=None): """If there is an x such that seq[x] == value and lo <= x < hi return the largest such x, else raise ValueError""" seqlen = len(seq) if lo < 0: lo += seqlen if lo < 0: lo = 0 if hi is None: hi = seqlen elif hi < 0: hi += seqlen if hi < 0: hi = 0 lo = seq.index(value, lo, hi) while True: try: lo = seq.index(value, lo + 1, hi) except ValueError: return lo if __name__ == "__main__": import sys av = sys.argv print rindex(av[4:], av[1], int(av[2]), int(av[3])) 8<--- end rindex.py --- Cheers, John Apr 7 '07 #11