2012-05-15 14 views
22

私は辞書がいっぱいです。辞書から任意の要素にアクセスするPythonic方法

print "Amongst our dictionary's items are such diverse elements as: %s" % arb(dictionary) 

私は1つの任意の項目を覗いてみたいと思います。 ランダムである必要はありません。

私はこれを実装する多くの方法を考えることができますが、それらはすべて無駄に見えます。私はPythonで好みのイディオムがあるのか​​、それとも欠けているのであれば(さらに良いのか)疑問に思います。

def arb(dictionary): 
# Creates an entire list in memory. Could take a while. 
    return list(dictionary.values())[0] 

def arb(dictionary): 
# Creates an entire interator. An improvement. 
    for item in dictionary.itervalues(): 
     return item 

def arb(dictionary): 
# No iterator, but writes to the dictionary! Twice! 
    key, value = dictionary.popitem() 
    dictionary[key] = value 
    return value 

私はパフォーマンスが十分に重大(まだ)この問題は、私は時期尚早の最適化と非難できることではない位置にいるが、私はので、もし、私のPythonのコーディングスタイルを改善しようとしています容易に理解できる変形があり、それを採用するのが良いでしょう。これは、Python 3のように、同様のpython 2に動作しますが、パイソン2に、それはこのようにそれを行うには、より効率的です

return next(iter(dictionary.values())) 

:私の意見では、あなたの第二の溶液に似ていますが、もう少し明らか

+7

'dictionary.itervalues()。next()はどうですか?それは少なくともあなたの2番目の 'arb'関数よりも優れています。 – srgerg

+0

@sgerg私はそれを提出しようとしていたが、あなたは先に進む。 :D – jamylak

+0

彼らは通話中に異なるアイテムにする必要がありますか?これらはすべて同じ項目を返します。 –

答えて

26

return next(dictionary.itervalues()) 
+0

を使うべきです。 – jamylak

+4

dictが空の場合、StopIterationが呼び出されることに注意してください。 – yak

+5

しかし、 'StopIteration'を避けたければ、デフォルト値を指定することができます。 'next(dictionary.itervalues()、None)'です。 –

1

randomを使用しない理由は?

import random 

def arb(dictionary): 
    return random.choice(dictionary.values()) 

これは、結果が純粋に任意であり、実装上の副作用ではないことを意味することは明らかです。パフォーマンスが実際の問題になるまでは、常にスピードを上回ります。

dict_valuesがインデックス作成をサポートしていないことは残念ですが、代わりに値ビューを渡すことができればうれしいです。

更新:誰もがパフォーマンスに執着しているので、上記の関数は1億アイテムのdictからランダムな値を返すために12038msをとします。明確なコードに依拠することは、それが成立するという驚くべきパフォーマンスヒットではありません。全体values/itervalues/viewvalues混乱を回避

+2

選択された要素がランダムである必要がないと指定されている場合、これは時間の無駄です。 docstring(と名前!)は、そのような観測には完全に十分です。 –

+1

名前が「任意」で、アクションがキーを反復するのであれば、その名前は私にはわかりません。だから、docstringが必要です。あなたのコードが何か他のことをしている理由を説明するためにdocstringを書かなければならない場合、答えはより明確なコードを書くことでしょう。 –

+1

このような操作では、120ミリ秒はまったく受け入れられません。これはマイクロ秒以下で完了します。以前に 'd [next(iter(d))]'を使っていた場所にこれを置くと、文字通り何百万分も遅くなります。 – user2357112

10

、これはPython2かのpython3

で同様に動作
dictionary[next(iter(dictionary))] 

代わりにあなたは発電機が

next(dictionary[x] for x in dictionary) 
+0

あなたは単に 'next(iter(dictionary.values()))' –

+0

@ Ev.Kounisも行うことができますが、python2では余分なリストが作成されます。 –

+0

'map'もPython 2でリストを作成します。 – user2357112

2

を表現好む場合、私は疑問が大幅に回答されていると信じてうまくいけば、この比較は、クリーンなコードと時間のトレードオフについてのいくつかの光を放つでしょう:

ここ

結果は以下のとおりです。

('pop', 0.0021750926971435547) 
('iter', 0.002003908157348633) 
('list', 0.047267913818359375) 
('insert', 0.0010859966278076172) 

iterkeysを使用してアイテムをpopingし、再挿入、その後速いだけで限界ですが、10倍のの速いリストを作成し、そこからランダムにオブジェクトを選択し、次にようです。

関連する問題