2014-05-24 52 views
3

我有想重新洗牌,像这样的OrderedDict: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?

回答

3

您不能random.shuffle an OrderedDict因为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) 

但我不知道这是否是更具可读性和审美。