Daquicker
Daquicker

Reputation: 525

python random.shuffle() in a while loop

I have a list:

    k = [1,2,3,4,5]

Now I want 3 permutations of this list to be listed in another list but when I do this:

    x = []
    i = 0
    while i < 3:
        random.shuffle(k)
        x.append(k)
        i += 1

I end up with 3 times the same permutation of k in x, like this:

    x = [[1,3,5,2,4], [1,3,5,2,4], [1,3,5,2,4]]

In stead of what I would like, something like this:

    x = [[1,5,4,2,3], [1,3,5,2,4], [5,3,4,1,2]]

Note that it is not possible due to the way the data in k is gathered to place k inside the loop, as for I know this would solve the problem. The real code is this:

    def create_random_chromosomes(genes):
        temp_chromosomes = []
        chromosomes = []
        i = 0
        while i < 2000:
            print(genes)
            random.shuffle(genes)
            temp_chromosomes.append(genes)
            i += 1
        print(temp_chromosomes)
        for element in temp_chromosomes:
            if element not in chromosomes:
                chromosomes.append(element)
        return chromosomes

Upvotes: 3

Views: 1702

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1125208

Shuffling a list changes it in-place, and you are creating 3 references to the same list. Create a copy of the list before shuffling:

x = []
for i in range(3):
    kcopy = k[:]
    random.shuffle(kcopy)
    x.append(kcopy)

I've simplified your loop as well; just use for i in range(3). Or, to place this in the context of your full method:

def create_random_chromosomes(genes):
    temp_chromosomes = []
    chromosomes = []
    for i in range(2000):
        print(genes)
        randomgenes = genes[:]
        random.shuffle(randomgenes)
        temp_chromosomes.append(randomgenes)
    print(temp_chromosomes)
    for element in temp_chromosomes:
        if element not in chromosomes:
            chromosomes.append(element)
    return chromosomes

You can further simplify the above by using a set to weed out dupes:

def create_random_chromosomes(genes):
    chromosomes = set()
    randomgenes = genes[:]
    for i in range(2000):
        random.shuffle(randomgenes)
        chromosomes.add(tuple(randomgenes))
    return list(chromosomes)

This uses a tuple copy of the random genes list to fit the hashable constraint of set contents.

You can then even ensure that you return 2000 unique items regardless:

def create_random_chromosomes(genes):
    chromosomes = set()
    randomgenes = genes[:]
    while len(chromosomes) < 2000:
        random.shuffle(randomgenes)
        chromosomes.add(tuple(randomgenes))
    return list(chromosomes)

Upvotes: 8

Related Questions