30

私はアイテムでいっぱいの辞書を持っています。単一の任意のアイテムをのぞき見したい:

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

どのアイテムでも構いません。ランダムである必要はありません。

これを実装する方法はたくさん考えられますが、どれも無駄に思えます。Pythonで推奨されるイディオムがあるかどうか、または(さらに良い)1つが欠けているかどうか疑問に思っています。

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

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

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

私はパフォーマンスが(まだ)重要ではないという立場にあるので、時期尚早の最適化で非難される可能性がありますが、Pythonコーディングスタイルを改善しようとしているので、簡単に理解できるバリアントがある場合は、それを採用するのは良いことです。

4

4 に答える 4

34

私の意見では、2番目の解決策と似ていますが、もう少し明白です。

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

これは、Python2とPython3で機能しますが、Python 2では、次のように実行する方が効率的です。

return next(dictionary.itervalues())
于 2012-05-15T03:09:15.860 に答える
10

values//混乱全体を回避し、これはPython2またはPython3でも同様に機能しitervaluesますviewvalues

dictionary[next(iter(dictionary))]

あるいは、ジェネレータ式を好む場合

next(dictionary[x] for x in dictionary)
于 2012-05-17T01:55:17.103 に答える
2

質問は大幅に回答されたと思いますが、この比較によって、クリーンなコードと時間のトレードオフが明らかになることを願っています。

from timeit import timeit
from random import choice
A = {x:[y for y in range(100)] for x in range(1000)}
def test_pop():
    k, v= A.popitem()
    A[k] = v

def test_iter(): k = next(A.iterkeys())

def test_list(): k = choice(A.keys())

def test_insert(): A[0] = 0

if __name__ == '__main__':
    print('pop', timeit("test_pop()", setup="from __main__ import test_pop", number=10000))
    print('iter', timeit("test_iter()", setup="from __main__ import test_iter", number=10000))
    print('list', timeit("test_list()", setup="from __main__ import test_list", number=10000))
    print('insert', timeit("test_insert()", setup="from __main__ import test_insert", number=10000))

結果は次のとおりです。

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

iterkeysを使用すると、アイテムをポップして再挿入するよりもわずかに速くなりますが、リストを作成してそこからランダムなオブジェクトを選択するよりも10倍速くなります。

于 2013-10-18T17:25:13.183 に答える
0

使ってみませんrandomか?

import random

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

これにより、結果が純粋に恣意的であり、実装の副作用ではないことが非常に明確になります。パフォーマンスが実際の問題になるまでは、常に速度よりも明確に行ってください。

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

更新:誰もがパフォーマンスに夢中になっているため、上記の関数は100万アイテムのdictからランダムな値を返すのに120ミリ秒未満かかります。明確なコードに依存することは、それが行われている驚くべきパフォーマンスヒットではありません。

于 2012-05-15T06:59:06.493 に答える