保证改组列表

时间:2019-05-07 20:45:57

标签: python list shuffle reorderlist

鉴于列表/有序集合,有一种方法可以对其成员进行保证改组/重新排序(这意味着没有元素处于与以前相同的位置),而无需进行反复试验?我在这里使用python,但是显然适用于具有这种结构的任何语言。

例如,如果我有一个列表l = [1, 2, 3, 4, 5]并随机洗牌:

import random                                                                                                                                                                                                                                                                                                                             

for _ in range(5): 
    random.shuffle([1,2,3,4,5]); 
    print(l) 
[1, 2, 3, 5, 4] # 1,2,3
[2, 4, 3, 1, 5] # 3, 5
[2, 1, 4, 5, 3] # OK!
[2, 5, 3, 1, 4] # 3
[5, 3, 4, 2, 1] # OK!

您可以看到只有第3个和第4个输出的所有元素确实在列表中的不同位置,而在其他情况下,我编写了保留在相同位置的列表元素。

还有一些更体贴的方法,例如在每个位置都忽略有问题的元素:

l=[1,2,3,4,5]
shuffled = []
for i in l:
    sample_from = [x for x in l if x not in shuffled + [i]]
    try:
        shuffled.append(random.sample(sample_from, 1)[0])
    except:
        print("Attempted to sample from", sample_from)
        break
    print("Shuffled portion:", shuffled)

可能导致错误,而没有可行的解决方案,例如:

Shuffled portion: [2]
Shuffled portion: [2, 4]
Shuffled portion: [2, 4, 1]
Shuffled portion: [2, 4, 1, 3]
Attempted to sample from []

5恰好保留在最后的位置,没有其他位置可替代原始位置。我猜想到了这个位置时,我可以将剩余的5换成随机排列的列表中的任何元素。

但是,如果没有这种手动技巧,是否还有其他更简单,更漂亮,更算法的方法来实现这一目标? 谢谢!

1 个答案:

答案 0 :(得分:0)

要生成乱序,可以使用Fisher-Yates改组算法,并在选择要交换的索引时将当前索引排除在考虑范围之外(即,不允许与其自身交换元素)。

相关问题