如何查找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
如果找不到该项目,将会引发StopIteration
exception; 你可以捕捉到,并提出一个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
的全部接口(包括可选的start
和stop
参数)。 我没有在这个问题的答案中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)