简体   繁体   English

如何以随机顺序循环遍历 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)

When I loop over the (key,value) pairs of a dictionary, is the order deterministic?当我遍历字典的(key,value)对时,顺序是否确定? How can I loop over them in a random order?如何以随机顺序循环遍历它们? Below works when the dictionary is small, but incurs memory error when there are thousands of pairs.下面在字典很小的时候工作,但是当有数千对时会导致内存错误。

from itertools import permutations

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

It should be relatively simple to shuffle your entries before iterating over them.在迭代之前对条目进行混洗应该相对简单。

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

This makes sense for cpython3.6 (python3.7) and greater because dictionaries remember their insertion order.这对于 cpython3.6 (python3.7) 和更高版本是有意义的,因为字典会记住它们的插入顺序。 On lower versions the result is not deterministic (it's a bit more nuianced than "not deterministic", actually, but this will do).在较低版本上,结果不是确定性的(实际上,它比“非确定性”要麻烦一些,但这确实可以)。

Note that the output of shuffle can also be made deterministic by seeding the randomizer.请注意, shuffle的输出也可以通过为随机数设定种子来确定。 "True randomness" is still only a concept - computers come close to achieving it though. “真正的随机性”仍然只是一个概念——不过计算机已经接近实现它了。 Most randomizer routines are a tradeoff between randomness and performance.大多数随机器例程是随机性和性能之间的权衡。

Note that you're OOM'ing because you're generating every single permutation of your dictionary (when in reality you just want one, random permutation, not all of them).请注意,您正在 OOM,因为您正在生成字典的每一个排列(实际上您只想要一个随机排列,而不是全部)。

When I loop over the (key,value) pairs of a dictionary, is the order deterministic?当我遍历字典的 (key,value) 对时,顺序是否确定?

This depends on what version of Python you're using.这取决于您使用的 Python 版本。

  • For Python < 3.6, the order is inconsistent, but not truly random.对于 Python < 3.6,顺序是不一致的,但不是真正随机的。 It will likely be different for different Python implementations, but you can't count on it being the same or not the same for two different people or two different runs.对于不同的 Python 实现,它可能会有所不同,但您不能指望它对于两个不同的人或两个不同的运行是否相同或不同。
  • For Python 3.6 ( specifically CPython ), the iteration order happens to be the same as the order of insertion, but it's still not "officially" guaranteed对于 Python 3.6(特别是 CPython ),迭代顺序恰好与插入顺序相同,但仍不能“正式”保证
  • For Python > 3.6, iteration order is explicitly guaranteed to be the order of insertion.对于 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]}')

You can make a shuffled list of the dictionary's keys, and then iterate over that.您可以创建一个无序的字典键列表,然后对其进行迭代。 This means you have to make a copy of all the keys, but it avoids making a copy of the values.这意味着您必须制作所有键的副本,但它避免制作值的副本。 Depending on what is in your dictionary, this may save you some memory.根据您的字典中的内容,这可能会为您节省一些记忆。

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)

(Disclaimer: I haven't tested whether it actually saves memory over cs95's solution, or other solutions. Intuitions about memory use and performance can often be wrong, so you should test how this code works on your data to see how it compares to other solutions.) (免责声明:我还没有测试过它是否真的比 cs95 的解决方案或其他解决方案节省了内存。关于内存使用和性能的直觉往往是错误的,所以你应该测试这段代码如何处理你的数据,看看它与其他解决方案相比如何解决方案。)

A dict is an unordered set of key-value pairs. dict 是一组无序的键值对。 When you iterate a dict, it is effectively random.当您迭代一个 dict 时,它实际上是随机的。 But to explicitly randomize the sequence of key-value pairs, you need to work with a different object that is ordered, like a list.但是要显式地随机化键值对的序列,您需要使用不同的有序对象,例如列表。 dict.items(), dict.keys(), and dict.values() each return lists, which can be shuffled. dict.items(), dict.keys(), 和 dict.values() 每个返回列表,可以洗牌。 hope this help you in any way希望这能以任何方式帮助你

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM