如何对一个列表中非连续的元素进行随机排序?

3

我有一个类似以下的Python列表:

["Apple", "Banana", "Coconut", "Durian", "Elderberry", "Fig", "Guava"]

我的目标是对列表进行洗牌,使某些元素被洗牌,而其他元素保持原位。
例如,如果要洗牌第0、1、2、4和6个元素,则该次洗牌的可能结果如下:
["Elderberry", "Banana", "Apple", "Durian", "Guava", "Fig", "Coconut"]

我该如何做?random.shuffle似乎只支持单个对象/切片。单独对每个切片进行洗牌只会在每个切片之间进行洗牌,而不是在所有切片中进行洗牌。


创建一个仅包含您想要洗牌的项目的列表,对其进行洗牌,然后将非洗牌项目插入所需位置。 - John Gordon
4个回答

3

这样做很有用 -- 与 random.shuffle() 不同,它返回列表的一个新副本。

import random


def shuffle_some(source, shuffle_indices):
    # Get the things to shuffle by the given indices
    to_shuffle = [source[i] for i in shuffle_indices]
    # and shuffle them.
    random.shuffle(to_shuffle)

    # Take a shallow copy of the source list so we can
    # modify it...
    shuffled = source[:]
    # And iterate through pairs of indices in the `to_shuffle`
    # list and the target indices to place them...
    for i, source_index in enumerate(shuffle_indices):
        # ... and put the shuffled items into place.
        shuffled[source_index] = to_shuffle[i]
    return shuffled


s = ["Apple", "Banana", "Coconut", "Durian", "Elderberry", "Fig", "Guava"]

for x in range(5):
    print(shuffle_some(s, (0, 3, 4)))

输出结果如下:

['Elderberry', 'Banana', 'Coconut', 'Apple', 'Durian', 'Fig', 'Guava']
['Durian', 'Banana', 'Coconut', 'Apple', 'Elderberry', 'Fig', 'Guava']
['Apple', 'Banana', 'Coconut', 'Durian', 'Elderberry', 'Fig', 'Guava']
['Apple', 'Banana', 'Coconut', 'Durian', 'Elderberry', 'Fig', 'Guava']
['Apple', 'Banana', 'Coconut', 'Elderberry', 'Durian', 'Fig', 'Guava']

2

可以把它想像成将一副牌分成两堆——你想要洗牌的一堆和你想保持顺序的一堆。将第二堆中的牌按照原有顺序排列,然后洗牌第一堆,并将洗好的牌发放到剩余空位上。

>>> import random
>>> fruits = ["Apple", "Banana", "Coconut", "Durian", "Elderberry", "Fig", "Guava"]
>>> shuffle_indices = (0, 1, 2, 4, 6)
>>> shuffled_items = random.sample([f for i, f in enumerate(fruits) if i in shuffle_indices], len(shuffle_indices))
>>> shuffled_fruits = [shuffled_items.pop() if i in shuffle_indices else f for i, f in enumerate(fruits)]
>>> shuffled_fruits
['Banana', 'Guava', 'Coconut', 'Durian', 'Apple', 'Fig', 'Elderberry']

0

你可以自己硬编码实现这个功能。

你可以提取想要洗牌的值,然后将它们洗牌。最后再重新输入到原始数据中。

def my_shuffle(list_, *args):
    shuffle_these = []
    for i in args:
        shuffle_these.append(list_[i])
    random.shuffle(shuffle_these)
    for integer, i in enumerate(list_):
        if integer in args:
            value = args.index(integer)
            list_[integer] = shuffle_these[value]
    return list_

print(my_shuffle([1, 2, 3, 4, 5, 6, 7], 1, 3, 6)) #this will shuffle the indices 1, 3, and 6

结果:

[1, 4, 3, 2, 5, 6, 7]

0

以下更简单的代码可以解决问题:

from random import shuffle

def funct(all_elem, indices):
    to_shuffel = all_elem.copy()
    for index in sorted(indices, reverse=True):
        del to_shuffel[index]

    shuffle(to_shuffel)
    for index in indices:  # Add the static elements to the shuffled list, accordingly.
        to_shuffel.insert(index, all_elem[index])
    return to_shuffel
    

创建一个函数,该函数接收要洗牌的列表和一组索引,这些索引将告诉哪些部分的列表应保持不变。创建一个包含可洗牌元素的列表,对它们进行洗牌,并在最后将固定元素插入到新洗牌列表上的正确位置。
例如:
list = ["Apple", "Banana", "Coconut", "Durian", "Elderberry", "Fig", "Guava"]
print(funct(list, (0, 1)))

输出:

['Apple', 'Banana', 'Fig', 'Elderberry', 'Durian', 'Coconut', 'Guava']

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接