Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copying lists in python

I am relatively new to Python. I am trying to come up with a function that takes a list, adds +1 to a value at random in that list, and then places a new list with the modified value as a new index.

For instance, if I have

blank=[]
list_one=[1,2,3,4,5] # 

The possible outcome might be

blank=[ [1,2,3,4,5], [1,3,3,4,5],[1,3,3,4,6],[2,3,3,4,6],[2,4,3,4,6] ]

So the function takes blank[0], copies and modifies it, and returns it as blank[1]. Similarly, the function takes blank[1], copies it and modifies it, and returns it as blank[2]

This is my code:

import random
list_one=[1,2,3,4,5]
def new_function(value):
    for i in range(1,value):
        list_copy=list_one[:]
        blank.append(list_copy)
        x=random.choice(blank[i])
        y=blank[i].index(x)
        blank[i][y]=x+1
    return blank

print new_function(4) 
"""Yields [ [1,2,3,4,5],[1,3,3,4,5],[2,2,3,4,5],[1,2,4,4,5] ] 
   (this is the list, blank)"""

my problem is that blank[1], blank[2], and blank[3] are all modifications of blank[0], when each indexed list should be a modification of the previous indexed list.

What am I doing wrong here???

like image 598
Nikhil Chandok Avatar asked Mar 06 '26 12:03

Nikhil Chandok


2 Answers

The issue is that you always copy the original list, not the new one. This is easily solved by using the same name for the new list, thus, when the loop comes round again, the new list is copied:

import random

def randomly_increment(seq, n):
    for _ in range(n):
        x = random.randrange(len(seq))
        seq = list(seq)
        seq[x] += 1
        yield seq

Which I believe works as intended:

>>> list(randomly_increment([1, 2, 3, 4, 5], 4))
[[1, 2, 4, 4, 5], [1, 2, 4, 5, 5], [1, 2, 4, 5, 6], [1, 2, 4, 6, 6]]

Other changes:

  • Rather than building a list, this is a generator, which is generally more flexible and easier to read/write. If you need a list, then wrap the call with list() as above.
  • Rather than making a random choice, then finding it's place to change it, it makes more sense to pick a place, and change it. This also avoids the issue where seq.index() will return the first value matching the given one, not necessarily the 'picked' one.
  • Using list(seq) to copy over seq[:], as noted in my comment. This is more readable.
like image 186
Gareth Latty Avatar answered Mar 08 '26 01:03

Gareth Latty


You start your range from 1, when they should start from 0, Also, you always copy from list_one and never update it, hence they are all copies of the original list, and not the previously modified one, here's the fixed code

import random
list_one=[1,2,3,4,5]
blank = []
def new_function(value):
    global list_one
    for i in range(value):
        list_copy = list_one[:]
        blank.append(list_copy)
        x=random.choice(blank[i])
        y=blank[i].index(x)
        blank[i][y]=x+1
        list_one = list_copy
    return blank
print new_function(4)

This gave me a random output of

[[2, 2, 3, 4, 5], [3, 2, 3, 4, 5], [3, 2, 3, 4, 6], [3, 2, 3, 5, 6]]

which matches your description.

Also, instead of choosing an element from the list, why not choose a random index and then modify it?

def new_function(value):
    global list_one
    for i in range(value):
        list_copy=list_one[:]
        blank.append(list_copy)
        x=random.randrange(len(list_copy))
        blank[i][x] += 1
        list_one = list_copy
    return blank
like image 40
Sukrit Kalra Avatar answered Mar 08 '26 03:03

Sukrit Kalra



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!