3

我有一个 OrderedDict 想像这样洗牌:

od = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
random.shuffle(od)

不幸的是,这不起作用(python3),并且KeyError: 0引发了异常。我工作的替代方法是转换为列表、随机播放并重建 OrderedDict:

od_tmp = list(od.items())
random.shuffle(od_temp)
od = OrderedDict(od_tmp)

由于 OrderedDict 有顺序,所以能够直接排序似乎是合理的。转换为列表效率低下。

问题是:

  • 有没有比上面的解决方案更好的方法?(不诉诸仅使用列表)
  • 为什么我不能随机播放 OrderedDict?
4

1 回答 1

4

您不能random.shuffle使用 OrderedDict,因为它是在考虑序列random.shuffle的情况下编写的。不幸的是,最好的 shuffle 算法(Fisher-Yates shuffle)需要随机访问才能有效,但是 OrderedDict 不提供基于顺序的随机访问(仅基于密钥)。可能有一种聪明而快速的方法来洗牌底层链表,但我不知道。

您可以实现按顺序迭代的 Fisher-Yates 洗牌,而不是进行随机访问,但这会更慢(二次复杂度和相当高的常数)。复制较少且不构造无意义的元组的一个选项是仅对键进行洗牌,然后对原始 OrderedDict 重新排序:

keys = list(od)
random.shuffle(keys)
for key in keys:
    od.move_to_end(key)

但我不确定这是否更具可读性和美观性。

于 2014-05-24T20:27:23.020 回答