次のようなコードがあります。
_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]
_
同じことを達成するよりクリーンな方法はありますか?リストがソートされていないと仮定しましょう。
Try-except句を使用することについて「汚い」ことは何もありません。これがPythonicの方法です。 ValueError
は、.index
メソッドのみ。そこにある唯一のコードだからです!
コメントに回答するには:
Pythonでは、 許可を得るよりも許しを求める方が簡単 哲学が確立されており、 no index
は、他の問題に対してこのタイプのエラーを発生させません。考えられることではありません。
thing_index = thing_list.index(elem) if elem in thing_list else -1
1行。シンプル。例外なく。
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 )
ValueError
を使用するコードに問題はありません。例外を回避したい場合は、もう1つのライナーがあります。
thing_index = next((i for i, x in enumerate(thing_list) if x == thing), -1)
この問題は言語哲学の一つです。 Javaたとえば、例外は フロー制御 ではなく、エラーが発生した「例外的な状況」でのみ実際に使用されるべきであるという伝統が常にありました。当初、これはJava例外は遅かったので、パフォーマンス上の理由からでしたが、今では受け入れられているスタイルになりました。
対照的に、Pythonは、ここで説明しているValueError
を上げるなど、常に例外を使用して通常のプログラムフローを示しています。Pythonスタイルで、それがどこから来たのかはもっとたくさんあります。さらに一般的な例は StopIteration
exception で、これはイテレータのnext()
これ以上値がないことを通知するメソッド。
これを頻繁に行う場合は、ヘルパー関数でそれを片付けた方が良いでしょう:
def index_of(val, in_list):
try:
return in_list.index(val)
except ValueError:
return -1
これはどうですか:
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:
これは、他の機能にすでにあるコードです。
これはどうですか:
temp_inx = (L + [x]).index(x)
inx = temp_inx if temp_inx < len(L) else -1
リストの「.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
>>>
これはどうですか ???? :
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