web-dev-qa-db-ja.com

Pythonでlist.index(might-not-exist)を処理する最良の方法は?

次のようなコードがあります。

_thing_index = thing_list.index(thing)
otherfunction(thing_list, thing_index)
_

わかりましたので、それは簡単ですが、あなたはアイデアを得る。 thingは実際にはリストにない可能性があります。その場合は、-1を_thing_index_として渡します。他の言語では、これは、要素が見つからなかった場合にindex()が返すことを期待するものです。実際、ValueErrorをスローします。

私はこれを行うことができます:

_try:
    thing_index = thing_list.index(thing)
except ValueError:
    thing_index = -1
otherfunction(thing_list, thing_index)
_

しかし、これは汚い感じがし、プラスValueErrorが他の何らかの理由で発生する可能性があるかどうかもわかりません。ジェネレーター関数に基づいた次のソリューションを思いつきましたが、少し複雑に思えます:

_thing_index = ( [(i for i in xrange(len(thing_list)) if thing_list[i]==thing)] or [-1] )[0]
_

同じことを達成するよりクリーンな方法はありますか?リストがソートされていないと仮定しましょう。

90
Draemon

Try-except句を使用することについて「汚い」ことは何もありません。これがPythonicの方法です。 ValueErrorは、.indexメソッドのみ。そこにある唯一のコードだからです!

コメントに回答するには:
Pythonでは、 許可を得るよりも許しを求める方が簡単 哲学が確立されており、 no indexは、他の問題に対してこのタイプのエラーを発生させません。考えられることではありません。

56
SilentGhost
thing_index = thing_list.index(elem) if elem in thing_list else -1

1行。シンプル。例外なく。

43
Emil Ivanov

dict type には get function があります。ここで、キーがディクショナリに存在しない場合、getの2番目の引数は返される値です。同様に setdefault があり、キーが存在する場合はdictの値を返します。それ以外の場合は、デフォルトパラメータに従って値を設定し、デフォルトパラメータを返します。

list型を拡張してgetindexdefaultメソッドを作成できます。

class SuperDuperList(list):
    def getindexdefault(self, elem, default):
        try:
            thing_index = self.index(elem)
            return thing_index
        except ValueError:
            return default

それは次のように使用できます:

mylist = SuperDuperList([0,1,2])
index = mylist.getindexdefault( 'asdf', -1 )
15
Ross Rogers

ValueErrorを使用するコードに問題はありません。例外を回避したい場合は、もう1つのライナーがあります。

thing_index = next((i for i, x in enumerate(thing_list) if x == thing), -1)
5
jfs

この問題は言語哲学の一つです。 Javaたとえば、例外は フロー制御 ではなく、エラーが発生した「例外的な状況」でのみ実際に使用されるべきであるという伝統が常にありました。当初、これはJava例外は遅かったので、パフォーマンス上の理由からでしたが、今では受け入れられているスタイルになりました。

対照的に、Pythonは、ここで説明しているValueErrorを上げるなど、常に例外を使用して通常のプログラムフローを示しています。Pythonスタイルで、それがどこから来たのかはもっとたくさんあります。さらに一般的な例は StopIteration exception で、これはイテレータのnext()これ以上値がないことを通知するメソッド。

3
Tendayi Mawushe

これを頻繁に行う場合は、ヘルパー関数でそれを片付けた方が良いでしょう:

def index_of(val, in_list):
    try:
        return in_list.index(val)
    except ValueError:
        return -1 
1
Veneet Reddy

これはどうですか:

otherfunction(thing_collection, thing)

関数インターフェイスのリストインデックスのように実装に依存するものを公開するのではなく、コレクションとモノを渡し、他の関数に「メンバーシップのテスト」問題を処理させます。他の関数がコレクション型に依存しないように記述されている場合、おそらく次のように開始されます。

if thing in thing_collection:
    ... proceed with operation on thing

thing_collectionがリスト、タプル、セット、または辞書の場合に機能します。

これはおそらく以下よりも明確です。

if thing_index != MAGIC_VALUE_INDICATING_NOT_A_MEMBER:

これは、他の機能にすでにあるコードです。

1
PaulMcG

これはどうですか:

temp_inx = (L + [x]).index(x) 
inx = temp_inx if temp_inx < len(L) else -1
1
Jie Xiong

リストの「.index()」メソッドにも同じ問題があります。私は例外をスローするという事実に問題はありませんが、それが非記述的なValueErrorであるという事実には強く反対します。ただし、それがIndexErrorであったかどうかは理解できました。

Pythonで有効なインデックスであるため、「-1」を返すことも問題になることがわかります。しかし現実的には、I neverは「.index()」メソッドが負の数を返すことを期待しています。

ここに1つのライナーがあります(わかりました、かなり長い行です...)、リストを1回だけ通過し、アイテムが見つからない場合は「なし」を返します。希望する場合は、-1を返すように書き直すのは簡単です。

indexOf = lambda list, thing: \
            reduce(lambda acc, (idx, elem): \
                   idx if (acc is None) and elem == thing else acc, list, None)

使い方:

>>> indexOf([1,2,3], 4)
>>>
>>> indexOf([1,2,3], 1)
0
>>>
0
haavee

これはどうですか ???? :

li = [1,2,3,4,5] # create list 

li = dict(Zip(li,range(len(li)))) # convert List To Dict 
print( li ) # {1: 0, 2: 1, 3: 2, 4:3 , 5: 4}
li.get(20) # None 
li.get(1)  # 0 
0
Alaa Akiel