30

我有一本字典,里面有很多东西。我想看看一个任意的项目:

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

我不在乎哪个项目。它不需要是随机的。

我可以想到很多实现这一点的方法,但它们似乎都很浪费。我想知道是否有任何 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 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

在我看来,与您的第二个解决方案类似,但更明显:

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

这在 python 2 和 python 3 中都有效,但在 python 2 中这样做更有效:

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

避免整个values//混乱,这在Python2itervaluesviewvaluesPython3中同样适用

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 不支持索引,如果能够传入值视图就好了。

更新:由于每个人都对性能如此着迷,因此上述函数需要 <120 毫秒才能从 100 万个项目的字典中返回一个随机值。依靠清晰的代码并没有像人们所说的那样获得惊人的性能。

于 2012-05-15T06:59:06.493 回答