修复第一个元素,对列表/数组的其余部分进行洗牌

时间:2012-07-29 02:56:15

标签: python shuffle

是否可以仅对给定列表(或numpy中的数组)的(连续)部分进行洗牌?

如果通常不可能,那么第一个元素被修复而列表/数组的其余部分需要被洗牌的特殊情况怎么样?例如,我有一个列表/数组:

to_be_shuffled = [None, 'a', 'b', 'c', 'd', ...]

第一个元素应该始终保留,而其余元素将反复洗牌。

一种可能的方法是首先对整个列表进行混洗,然后检查第一个元素,如果它不是特殊的固定元素(例如None),则将其位置与特殊元素的位置交换(然后需要查找)。

有没有更好的方法呢?

4 个答案:

答案 0 :(得分:9)

为什么不

import random
rest = to_be_shuffled[1:]
random.shuffle(rest)
shuffled_lst = [to_be_shuffled[0]] + rest

答案 1 :(得分:5)

numpy数组不会在切片上复制数据:

numpy.random.shuffle(a[1:])

答案 2 :(得分:4)

我认为尝试实施比你要求的更为通用的方法会很有趣和有教育意义。在这里,我将 indices 拖放到原始列表(而不是列表本身),不包括锁定的索引,并使用该索引列表从原始列表中挑选元素。这不是一个就地解决方案,而是作为生成器实现,因此您可以懒惰地选择元素。

如果可以改进,请随时编辑。

import random

def partial_shuf(input_list, fixed_indices):
    """Given an input_list, yield elements from that list in random order
    except where elements indices are in fixed_indices."""
    fixed_indices = sorted(set(i for i in fixed_indices if i < len(input_list)))
    i = 0
    for fixed in fixed_indices:
        aslice = range(i, fixed)
        i = 1 + fixed
        random.shuffle(aslice)
        for j in aslice:
            yield input_list[j]
        yield input_list[fixed]
    aslice = range(i, len(input_list))
    random.shuffle(aslice)
    for j in aslice:
        yield input_list[j]

print '\n'.join(' '.join((str(i), str(n))) for i, n in enumerate(partial_shuf(range(4, 36), [0, 4, 9, 17, 25, 40])))

assert sorted(partial_shuf(range(4, 36), [0, 4, 9, 17, 25, 40])) == range(4, 36)

答案 3 :(得分:3)

我从标准库random模块中找到了shuffle函数(在Lib\random.py中找到)并稍微修改它,以便它只调整由start和{指定的列表的一部分{1}}。它就是这样做的。享受!

stop

出于您的目的,使用from random import randint def shuffle(x, start=0, stop=None): if stop is None: stop = len(x) for i in reversed(range(start + 1, stop)): # pick an element in x[start: i+1] with which to exchange x[i] j = randint(start, i) x[i], x[j] = x[j], x[i] 作为1参数调用此函数应该可以解决问题。