如何以随机顺序遍历 Python 字典的项目?

How can I loop over the items of a Python dictionary in a random order?

D = {(1,1):2, (2,3):6, (3,4):12, (0,1):0, (4,9):36}

for (i,j),val in D.items():
    print(i,j,"-->",val)

当我遍历 (key,value) 对字典时,顺序是确定的吗?我怎样才能以随机顺序遍历它们?当字典很小时下面可以工作,但是当有数千对时会导致内存错误。

from itertools import permutations

P = list(permutations(D.items()))
for (i,j),val in sample(P,1)[0]:
    print(i,j,"-->",val)

在遍历条目之前打乱条目应该相对简单。

from random import shuffle

dict_as_list_of_entries = [*D.items()]
shuffle(dict_as_list_of_entries) # randomizes the order

for (i, j), value in dict_as_list_of_entries:
    # do something

这对 cpython3.6 (python3.7) 和更大的版本有意义,因为字典会记住它们的插入顺序。在较低版本上,结果不是确定性的(实际上,它比“非确定性”更令人讨厌,但这样做就可以了)。

请注意,shuffle 的输出也可以通过为随机化器设置种子来确定。 “真正的随机性”仍然只是一个概念——不过计算机已经接近实现它了。大多数随机化器例程是随机性和性能之间的权衡。

请注意,您正在 OOM'ing,因为您正在生成字典的每一个排列(而实际上您只想要一个随机排列,而不是所有排列)。

字典是 key-value 对的无序集合。当你迭代一个 dict 时,它实际上是随机的。但是要显式随机化 key-value 对的序列,您需要使用一个不同的有序对象,例如列表。 dict.items()、dict.keys() 和 dict.values() 每个 return 列表,可以打乱顺序。希望这对你有任何帮助

When I loop over the (key,value) pairs of a dictionary, is the order deterministic?

这取决于您使用的 Python 版本。

  • 对于Python < 3.6,顺序不一致,但不是真正随机的。对于不同的 Python 实施,它可能会有所不同,但您不能指望它对于两个不同的人或两次不同的运行是相同的还是不同的。
  • 对于Python 3.6(特别是CPython),迭代顺序恰好相同作为插入顺序,但仍然不能“官方”保证
  • 对于Python > 3.6,明确保证迭代顺序是插入顺序。

How can I loop over them in a random order? Try randomizing the order of the keys, then looping over those:

import random

shuffled_keys = random.sample(D.keys(), len(D.keys()))
for k in shuffled_keys:
    print(f'{k} --> {D[k]}')

您可以创建字典键的随机列表,然后对其进行迭代。这意味着您必须复制所有键,但它避免了复制值。根据您字典中的内容,这可能会为您节省一些记忆。

import random

d = {(1, 1): 2, (2, 3): 6, (3, 4): 12, (0, 1): 0, (4, 9): 36}
for key in random.sample(d.keys(), k=len(d)):
    value = d[key]
    i, j = key
    print(i, j, "-->", value)

(免责声明:我还没有测试过它是否真的比 cs95 的解决方案或其他解决方案节省了内存。关于内存使用和性能的直觉通常是错误的,所以你应该测试这段代码如何处理你的数据以了解它与其他解决方案的比较。)