Python - shuffle only some elements of a list

user1227065 picture user1227065 · Mar 4, 2012 · Viewed 9.7k times · Source

I'm trying to shuffle only elements of a list on 3rd till last position so the 1st two will always stay in place e.g.

list = ['a?','b','c','d','e']

into

list = ['a?','b','d','e','c']

and for some reason this doesn't work:

list = ['a?','b','c','d','e']
import random
random.shuffle(list[2:])    
print list

Any know what am I doing wrong??

The only thing that works for me is so far this (EDITED):

lists = [['a?','b','c','d','e'],['1?','2','3','4','5','6','7']]
import random

for list in lists:
    copy = list[2:]
    random.shuffle(copy)
    list[2:] = copy

print lists

Think this is exactly what I needed.

Answer

bereal picture bereal · Mar 4, 2012

If you want to shuffle without copying, you may try to write your own mutable slice class, like follows (that's a rough implementation sketch, no boundary checks etc):

class MutableSlice(object):
    def __init__(self, baselist, begin, end=None):
        self._base = baselist
        self._begin = begin
        self._end = len(baselist) if end is None else end

    def __len__(self):
        return self._end - self._begin

    def __getitem__(self, i):
        return self._base[self._begin + i]

    def __setitem__(self, i, val):
        self._base[i + self._begin] = val

Then wrap the original list into it and feed to the standard shuffle:

>>> mylist = [1,2,3,4,5,6]
>>> slice = MutableSlice(mylist, 2)
>>> import random
>>> random.shuffle(slice)
>>> mylist
[1, 2, 4, 3, 5, 6]