web-dev-qa-db-ja.com

Pythonリストでアイテムの最後の出現を見つける方法

このリストがあるとしましょう:

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

ヘルプからわかる限り、文字列の最後の出現を返す組み込み関数はありません(indexの逆のような)。したがって、基本的に、最後に出現する"a"与えられたリストに?

61
Shaokan

あなたの例に示されているように実際に単一の文字を使用している場合、 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

ここでスライスすると、リスト全体のcopyが作成されます。短いリストの場合は問題ありませんが、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')
75
wim

イグナシオに似たワンライナーは、少しシンプル/クリアになりますが、

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

私には非常に明確でPythonicに思えます:一致する値を含む最高のインデックスを探しています。次、ラムダ、リバース、またはitertoolsは必要ありません。

29
alcalde

他の多くのソリューションでは、リスト全体を反復処理する必要があります。これはしません。

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
15
Isaac

wim'sIgnacio's の両方の回答が好きです。ただし、itertoolsは、ラムダにもかかわらず、もう少し読みやすい代替手段を提供すると思います。 (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
7
senderle
>>> (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

dictを使用

辞書キーは一意であり、タプルを使用して辞書キーを作成する場合、特定のキーの値の最後の割り当てのみが使用されるという事実を使用できます。他の回答で述べたように、これは小さなリストでは問題ありませんが、すべての一意の値の辞書を作成し、大きなリストでは効率的ではない場合があります。

dict(map(reversed, enumerate(li)))["a"]

6
4
piRSquared

list.rindexの完全なインターフェイス(オプションのstartおよびstopパラメーターを含む)を提供するlist.indexの最も効率的なバージョンを作成する作業を既に誰かが行っていることを期待して、私はここに来ました。この質問への回答、または here 、または here 、または here にそれが見つかりませんでした。だから私はこれを自分でまとめました...これに対する他の答えと他の質問からの提案を利用しています。

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%遅くなります。

2
dubiousjim

enumerate とリスト内包表記を使用して、最後のインデックスを取得するための1行のライナーを次に示します。

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

単純なループを使用します。

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))
0
Laurent LAPORTE

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

2の最後の出現を見つける必要がある場合

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

0
user2782561
from array import array
fooa = array('i', [1,2,3])
fooa.reverse()  # [3,2,1]
fooa.index(1)
>>> 2
0
cop4587
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))
0
user2426679
last_occurence=len(yourlist)-yourlist[::-1].index(element)-1

そのように簡単です。関数をインポートまたは作成する必要はありません。

0
Prabu M