为什么OrderedDict不能被洗牌?

时间:2014-05-24 20:13:24

标签: python-3.x shuffle ordereddictionary

我有一个想要像这样洗牌的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?

1 个答案:

答案 0 :(得分:4)

您不能random.shuffle订购OrderDict,因为random.shuffle的编写考虑了sequences。不幸的是,最好的混洗算法(Fisher-Yates shuffle)要求随机访问是有效的,但是OrderedDict不提供基于顺序的随机访问(仅基于密钥)。 可能是一种巧妙而快速的方式来对基础链表进行随机播放,但我并不知道任何链接列表。

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

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

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