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



假设我有这个列表:

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

据帮助所示,没有一个内置函数可以返回字符串的最后一次出现(就像index的相反(。那么,基本上,我如何在给定的列表中找到"a"的最后一个出现?

如果您实际上只使用如示例中所示的单个字母,那么str.rindex将很容易工作。这会引发一个ValueError,如果没有这样的项,则会引发与list.index相同的错误类。演示:

>>> li = ["a", "b", "a", "c", "x", "d", "a", "6"]
>>> ''.join(li).rindex('a')
6

对于更一般的情况,您可以在反向列表中使用list.index

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

这里的切片创建整个列表的副本。这对于短列表来说很好,但对于li非常大的情况,使用惰性方法可以提高效率:

def list_rindex(li, x):
    for i in reversed(range(len(li))):
        if li[i] == x:
            return i
    raise ValueError("{} is not in list".format(x))

一个线性版本:

next(i for i in reversed(range(len(li))) if li[i] == 'a')

一个类似Ignacio的单行线,除了更简单/更清晰一点之外,就是

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

对我来说,这似乎非常清楚和Python化:您正在寻找包含匹配值的最高索引。不需要nexts、lambdas、reversed或itertools。

许多其他解决方案都需要对整个列表进行迭代。事实并非如此。

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(list(enumerate(li))) if x[1] == 'a').next()[0]
6
>>> len(li) - (x for x in enumerate(li[::-1]) if x[1] == 'a').next()[0] - 1
6

我喜欢wim和Ignacio的答案。然而,我认为itertools提供了一个可读性稍高的替代方案,尽管有lambda。(对于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异常;您可以捕捉到它并引发一个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")

它也适用于非字符。测试:

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

dict

您可以使用字典键是唯一的这一事实,并且在使用元组构建字典键时,只会使用特定键的最后一个值赋值。正如其他答案中所述,这对于小列表来说很好,但它为所有唯一值创建了一个字典,对于大列表来说可能效率不高。

dict(map(reversed, enumerate(li)))["a"]
6
last_occurence=len(yourlist)-yourlist[::-1].index(element)-1

就这么简单。不需要导入或创建函数。

我来到这里,希望有人已经完成了编写list.rindex最高效版本的工作,该版本提供了list.index的完整接口(包括可选的startstop参数(。我在这个问题的答案中没有发现,或者在这里,或者在那里。所以我自己把这些放在一起。。。利用其他答案对这个问题和其他问题的建议。

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)的技术可以更节省空间:它不需要创建完整列表的反向副本。但在我的(随意的(测试中,它大约慢了50%。

Love@alcalde的解决方案,但面临ValueError:max((arg是一个空序列如果没有元素匹配条件。

为了避免错误设置默认值=无

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

使用一个简单的循环:

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))
lastIndexOf = lambda array, item: len(array) - (array[::-1].index(item)) - 1
def rindex(lst, val):
  try:
    return next(
      len(lst) - n
      for n, v in enumerate(reversed(lst), start=1)
      if v == val
    )
  except StopIteration:
    raise ValueError(f'{val} is not in list')

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

如果你需要找到最后出现的2

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

这里有一个小的线性函数,用于使用enumerate和列表理解来获得最后一个索引:

li = ["a", "b", "a", "c", "x", "d", "a", "6"]
[l[0] for l in enumerate(li) if l[1] == "a"][-1]

如果列表很小,您可以计算所有索引并返回最大值:

index = max(i for i, x in enumerate(elements) if x == 'foo')

相关内容

  • 没有找到相关文章

最新更新