0

In my script I need to generate a simple list of [1,2,3,4] values and then shuffle each one of those lists inside this list individually. I used random.shuffle() function which works fine on single arrays, but when I try to use it in a for loop the output is a list of shuffled arrays, but all of them identical:

[3, 1, 2, 4]
[3, 1, 2, 4]
[3, 1, 2, 4]
etc...

I have tried running the script with different python versions (2.7, 3.6) but the problem persists.

Here is a simplified code that represents the issue:

import random

numbers_list = [1,2,3,4]
#make a list of 10 numbers_list
list_of_lists = [numbers_list]*10

#shuffle every list inside list_of_lists
for i in list_of_lists:
    random.shuffle(i)

#print every list from list_of_lists
for a in list_of_lists:
    print(a)

Running the script multiple times results in different lists, but they always consist of a repeated one array. What can I do to fix it? Is it an issue with random.shuffle() or my script? What am I doing wrong?

Skelebot
  • 58
  • 9
  • At first glance, I'd say that you write 10 references to the sam object in the List. But I don't know the operation you use here `[numbers_list]*10 `. Did you test this syntax with other objects that return memory adresses so you can see if they are the same object? – hajef May 27 '19 at 15:41

2 Answers2

4

Your problem is this line:

list_of_lists = [numbers_list]*10

This creates a list of 10 references to the same list (numbers_list). Any change you make to any of the lists is reflected in all 10 copies - because they're the same list.

Do something like this instead:

list_of_lists = [numbers_list.copy() for _ in range(10)]
Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
  • 1
    So I guess that using [something] * number makes sense only if "something" is a number or a constant because if you do that like I did, you create a list of references that change together? Also thanks, that solved it. – Skelebot May 27 '19 at 15:54
  • Yup that's right. It's a pretty common "gotcha" in python. – Blorgbeard May 27 '19 at 15:57
0

Culprit is there:

numbers_list = [1,2,3,4]
#make a list of 10 numbers_list
list_of_lists = [numbers_list]*10

as now list_of_lists is in fact ONE list repeated 10 times, you could avoid that using .copy method as already shown or by replacing:

list_of_lists = [numbers_list]*10

with

list_of_lists = [list(numbers_list) for _ in range(10)]

or

list_of_lists = [numbers_list[:] for _ in range(10)]

First one might be readed I want 10 times new list based on numbers_list and second harness so-called slicing.

Daweo
  • 31,313
  • 3
  • 12
  • 25