2

Python/programming newbie here, trying to figure out what is going in with this while loop. First the code:

var_list = []
split_string = "pink penguins,green shirts,blue jeans,fried tasty chicken,old-style boots"

def create_variations(split_string):
    init_list = split_string.split(',')
    first_element = init_list[0]

    # change first element of list to prepare for while loop iterations
    popped = init_list.pop()
    added = init_list.insert(0, popped)

    while init_list[0] != first_element:
        popped = init_list.pop()
        added = init_list.insert(0, popped)
        print init_list # prints as expected, with popped element inserted to index[0] on each iteration
        var_list.append(init_list) # keeps appending the same 'init_list' as defined on line 5, not those altered in the loop!

    print var_list

create_variations(split_string)

My objective is to create all variations of the init_list, meaning that the indexes are rotated so that each index gets to be first just once. These variations are then appended to another list, which is the var_list in this code.

However, I am not getting the result I am expecting from the while loop. In the while loop, the piece of code print init_list actually prints the variations I want; but the next line of code var_list.append(init_list) does not append these variations. Instead the init_list as created on line 5 is repeatedly appended to the var_list.

What is going on here? And how can I get the different variations of the init_list created in the while loop to append to the var_list.

Output I expect for var_list:

[['fried tasty chicken', 'old-style boots', 'pink penguins', 'green shirts', 'blue jeans'],
 ['blue jeans', 'fried tasty chicken', 'old-style boots', 'pink penguins', 'green shirts'],
 ['green shirts', 'blue jeans', 'fried tasty chicken', 'old-style boots', 'pink penguins'],
 ['pink penguins', 'green shirts', 'blue jeans', 'fried tasty chicken', 'old-style boots']]
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
Darren Haynes
  • 1,343
  • 4
  • 18
  • 31

2 Answers2

6

Here some code that does what I think you want in a simpler fashion :

variations = []
items = [1,2,3,4,5]

for i in range(len(items)):
    v = items[i:] + items[:i]
    variations.append(v)

print variations

Output :

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

Or you can use this simple generator :

(items[i:] + items[:i] for i in range(len(items)))
Emil Davtyan
  • 13,808
  • 5
  • 44
  • 66
  • Thanks for providing these much nicer pieces of code. I have not used/studied generators yet, now I can go read up on the subject. And all in 1 neat line :-) – Darren Haynes Oct 14 '13 at 06:14
3

With this line

var_list.append(init_list)

you are adding a reference to init_list everytime. But you need to create a new list. Use this

var_list.append(init_list[:])

Explanation

When you are printing init_list, it prints the current state. When you are adding it to var_list, you are not adding the current state. You are adding a reference. So, when the actual list changes all references point to the same data.

And you can simplify your program like this

def create_variations(split_string):
    init_list = split_string.split(', ')
    for i in range(len(init_list)):
        var_list.append(init_list[:])
        init_list.insert(0, init_list.pop())

    print var_list
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • Thanks for clearing that up for me. It still puzzles me a little that `print init_list` in the while loop prints the variations, but `init_list` is not actually changed, thus the `[:]` needs to be added. But now I know that I need to do so while looping. – Darren Haynes Oct 14 '13 at 06:12
  • 1
    when you are printing that, it prints the current state. When you are adding, you are not adding the current state. You are adding a reference. So, when the actual list changes all references point to the same data. – thefourtheye Oct 14 '13 at 06:14
  • In Python 3.3+ there is now a `list.copy()` method for this. A little bit clearer syntax that does the same thing. – Rick Jul 06 '18 at 18:19