如何洗牌python列表以保留某些元素的出现?

如何洗牌python列表以保留某些元素的出现?,python,list,random,shuffle,Python,List,Random,Shuffle,我从整数列表开始: A=[1,2,5,3,4,6,7,8] 在一次洗牌之后,我希望一些元素(比如3、4和5)在一段时间内保持它们的出现顺序,而其余的元素可以随意洗牌。比如: 结果#1: A=[5,2,3,1,8,4,6,7] -或- 结果#2: A=[7,5,6,1,3,4,8,2] -但不是- 结果#3(无效结果) A=[7,4,6,1,3,5,8,2] 感谢所有建议 这是一种使用随机模块的方法 Ex: import random A = [ 1, 2, 5, 3, 4, 6, 7, 8 ]

我从整数列表开始:

A=[1,2,5,3,4,6,7,8]

在一次洗牌之后,我希望一些元素(比如3、4和5)在一段时间内保持它们的出现顺序,而其余的元素可以随意洗牌。比如:

结果#1: A=[5,2,3,1,8,4,6,7]

-或-

结果#2: A=[7,5,6,1,34,8,2]

-但不是-

结果#3(无效结果) A=[7,4,6,1,35,8,2]


感谢所有建议

这是一种使用
随机
模块的方法

Ex:

import random

A = [ 1, 2, 5, 3, 4, 6, 7, 8 ]
result = A[2:5]
del A[2:5]
while A:
    l = len(A)
    result.insert(random.randint(0, l), A.pop(random.randrange(l)))
print(result)
[1, 7, 6, 5, 8, 3, 4, 2]
[8, 1, 2, 7, 5, 3, 6, 4]
[8, 6, 7, 2, 1, 5, 3, 4]
[1, 7, 2, 8, 5, 3, 4, 6]
[6, 8, 7, 5, 1, 3, 4, 2]
[7, 2, 5, 6, 1, 3, 4, 8]
[1, 8, 5, 2, 3, 4, 6, 7]
[5, 7, 1, 6, 3, 8, 4, 2]
[1, 5, 7, 3, 2, 4, 8, 6]
[8, 2, 7, 6, 5, 3, 4, 1]
演示

def rand_shfl(lst):
    result = lst[2:5]
    del lst[2:5]
    while A:
        l = len(A)
        result.insert(random.randint(0, l), A.pop(random.randrange(l)))
    return result

for _ in range(10):
    A = [ 1, 2, 5, 3, 4, 6, 7, 8 ]
    print((rand_shfl(A)))
输出:

import random

A = [ 1, 2, 5, 3, 4, 6, 7, 8 ]
result = A[2:5]
del A[2:5]
while A:
    l = len(A)
    result.insert(random.randint(0, l), A.pop(random.randrange(l)))
print(result)
[1, 7, 6, 5, 8, 3, 4, 2]
[8, 1, 2, 7, 5, 3, 6, 4]
[8, 6, 7, 2, 1, 5, 3, 4]
[1, 7, 2, 8, 5, 3, 4, 6]
[6, 8, 7, 5, 1, 3, 4, 2]
[7, 2, 5, 6, 1, 3, 4, 8]
[1, 8, 5, 2, 3, 4, 6, 7]
[5, 7, 1, 6, 3, 8, 4, 2]
[1, 5, 7, 3, 2, 4, 8, 6]
[8, 2, 7, 6, 5, 3, 4, 1]

提取要在其中保持相对顺序的元素,按正常顺序洗牌,然后通过随机选择要插入的“保留”元素的索引将列表粘合在一起。如果在
操作中使用集合来加速
,那么所有的操作都是线性的,我对此并不在意。
保留
列表的顺序很重要

>>> import random
>>> L = [1, 2, 5, 3, 4, 6, 7, 8]
>>> keep = [2, 3, 4]
>>> kept = [L[i] for i in keep][::-1]
>>> unkept = [x for i, x in enumerate(L) if i not in keep]
>>> random.shuffle(unkept)
>>> idxes = random.sample(list(range(len(L))), k=len(keep))
>>> result = [kept.pop() if i in idxes else unkept.pop() for i in range(len(L))]
>>> result
[6, 5, 3, 8, 4, 1, 7, 2]
随机测试:

import random

def shuffle_with_fixed_order(L, keep):
    kept = [L[i] for i in keep][::-1]
    unkept = [x for i, x in enumerate(L) if i not in keep]
    random.shuffle(unkept)
    idxes = random.sample(list(range(len(L))), k=len(keep))
    return [kept.pop() if i in idxes else unkept.pop() for i in range(len(L))]
    
if __name__ == "__main__":
    for _ in range(5000):
        L = list(range(50))
        random.shuffle(L)
        keep = sorted(random.sample(L, k=20))
        shuffled = shuffle_with_fixed_order(L, keep)
        new_locs = [shuffled.index(L[i]) for i in keep]
        assert all(x < y for x, y in zip(new_locs, new_locs[1:]))
随机导入
def洗牌(固定顺序)(L,保留):
keep=[L[i]表示保留中的i][:-1]
unkept=[x代表i,如果i不在keep中,则枚举(L)中的x]
随机。洗牌(unkept)
idxes=random.sample(列表(范围(len(L)),k=len(keep))
返回[keeped.pop(),如果IDX中的i在范围(len(L))内,则返回unkept.pop()]
如果名称=“\uuuuu main\uuuuuuuu”:
对于范围内的(5000):
L=列表(范围(50))
随机。洗牌(L)
保持=分类(随机样本(L,k=20))
洗牌=按固定顺序洗牌(L,保持)
new_locs=[shuffled.index(L[i])表示保留中的i]
断言全部(x
以下内容可能适合您

import random
lst=[1, 2, 5, 3, 4, 6, 7, 8]
s_lst = {5:0,3:0,4:0}

idx_lst = [random.randint(0, len(lst)) for i in range(len(s_lst))]
idx_lst.sort()

for i, s in enumerate(s_lst.keys()):
    s_lst[s] = idx_lst[i]
    lst.remove(s)

random.shuffle(lst)
for k, v in s_lst.items():
    lst.insert(v, k)

print(lst)

欢迎来到SO!你有没有试图解决这个问题?如果是的话,你能把代码作为一个共享吗?谢谢。不清楚你想要实现什么。地点和事件之间有什么区别?您显示的预期输出正是
randon.shuffle(您的\u列表)
将产生的结果。规范似乎很清楚,OP希望5->3->4子列表永远不会改变顺序,因此
[7,4,6,1,3,5,8,2]
将是无效的结果。或者我是这么想的。这就是问题所在-这是您/我们的假设欢迎使用so,因为它会给我们一些代码,以便我们可以在开发环境中复制和删除这些代码,以便更好地理解问题。这里的IDX必须是不可替换的。另外,不确定为什么keep被洗牌。对于所示的示例来说效果很好。但也许值得让它更通用。e、 例如,当原始列表中没有连续出现5、3和4时。