如何查找Python列表中项目的最后一次出现

说我有这个清单:

li = ["a", "b", "a", "c", "x", "d", "a", "6"] 

至于帮助给我看,没有一个内build函数返回最后一个string(如index的反转)。 所以基本上,我怎样才能find给定列表中最后一次出现的"a"

如果您实际上只使用单个字母(如示例中所示),那么''.join(li).rfind('a')将很好地工作。 如果“a”不在列表中,它将返回-1

对于一般情况下,您可以使用:

 len(li) - 1 - li[::-1].index('a') 

如果'a'不在列表中,将会引发ValueError 。 这里的切片创build整个列表的副本 。 对于短列表来说没什么问题,但是对于li很大的情况,懒惰的方法可能会更好:

 # Python 3 version next(i for i,v in zip(range(len(li)-1, -1, -1), reversed(li)) if v == 'a') # Python 2 version import itertools as it indices = xrange(len(li)-1, -1, -1) gen = it.izip(indices, reversed(li)) next(i for i,value in gen if value == 'a') 

就像Ignacio's一样,除了简单/清晰之外,就是这样

 max(loc for loc, val in enumerate(li) if val == 'a') 

对我来说,这似乎很清楚,Pythonic:你正在寻找包含匹配值的最高索引。 没有下一个,lambdas,反转或itertools所需。

许多其他解决scheme需要迭代整个列表。 这不是。

 def find_last(lst, elm): gen = (len(lst) - 1 - i for i, v in enumerate(reversed(lst)) if v == elm) return next(gen, None) 

编辑:事后看来,这似乎是不必要的巫术。 我会做这样的事情,而不是:

 def find_last(lst, sought_elt): for r_idx, elt in enumerate(reversed(lst)): if elt == sought_elt: return len(lst) - 1 - r_idx 
 >>> (x for x in reversed([y for y in enumerate(li)]) if x[1] == 'a').next()[0] 6 >>> len(li) - (x for x in (y for y in enumerate(li[::-1])) if x[1] == 'a').next()[0] - 1 6 

我喜欢Wim和Ignacio的答案。 不过,我认为itertools提供了一个稍微可读的替代方法,尽pipe如此。 (对于Python 3;对于Python 2,使用xrange而不是range )。

 >>> from itertools import dropwhile >>> l = list('apples') >>> l.index('p') 1 >>> next(dropwhile(lambda x: l[x] != 'p', reversed(range(len(l))))) 2 

如果找不到该项目,将会引发StopIterationexception; 你可以捕捉到,并提出一个ValueError而不是像index

定义为一个函数,避免lambda快捷键:

 def rindex(lst, item): def index_ne(x): return lst[x] != item try: return next(dropwhile(index_ne, reversed(range(len(lst))))) except StopIteration: raise ValueError("rindex(lst, item): item not in list") 

它也适用于非字符。 testing:

 >>> rindex(['apples', 'oranges', 'bananas', 'apples'], 'apples') 3 

使用一个简单的循环:

 def reversed_index(items, value): for pos, curr in enumerate(reversed(items)): if curr == value: return len(items) - pos - 1 raise ValueError("{0!r} is not in list".format(value)) 
 def rindex(lst, val): try: return next(len(lst)-i for i, e in enumerate(reversed(lst), start=1) if e == val) except StopIteration: raise ValueError('{} is not in list'.format(val)) 

我来到这里希望能find有人已经完成了编写list.rindex的最高效版本的list.rindex ,它提供了list.index的全部接口(包括可选的startstop参数)。 我没有在这个问题的答案中find答案,或者在这里 ,或者在这里 ,或者在这里 。 所以我把它放在一起…利用其他答案的build议,以及其他问题。

 def rindex(seq, value, start=None, stop=None): """L.rindex(value, [start, [stop]]) -> integer -- return last index of value. Raises ValueError if the value is not present.""" start, stop, _ = slice(start, stop).indices(len(seq)) if stop == 0: # start = 0 raise ValueError('{!r} is not in list'.format(value)) else: stop -= 1 start = None if start == 0 else start - 1 return stop - seq[stop:start:-1].index(value) 

使用len(seq) - 1 - next(i for i,v in enumerate(reversed(seq)) if v == value)的技巧可以更加节省空间:它不需要创build完整列表的反转副本。 但是在我的(非正式的,偶然的)testing中,速度大约慢了50%。

val = [1,2,2,2,2,2,4,5]。

如果你需要find最后的发生2

last_occurence = (len(val) -1) - list(reversed(val)).index(2)

Interesting Posts