3

I have 2 lists:

one = [
    [1, 2, 3, 4],
    [2, 3, 4, 5],
    [3, 4, 5, 6],
    [4, 5, 6, 7]
    ]

two = [
    [one[0][0], one[0][1], one[1][0], one[1][1]],
    [one[0][2], one[0][3], one[1][2], one[1][3]],
    [one[2][0], one[2][1], one[3][0], one[3][1]],
    [one[2][2], one[2][3], one[3][2], one[3][3]]
    ]

When I input this one:

two[0][0] = 9

It comes out like this:

one: [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7]]
two: [[9, 2, 2, 3], [3, 4, 4, 5], [3, 4, 4, 5], [5, 6, 6, 7]]

How can I get the same changes as in 'two' list in 'one' list when I changes the element in 'two' list, so that:

one: [[9, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7]]
two: [[9, 2, 2, 3], [3, 4, 4, 5], [3, 4, 4, 5], [5, 6, 6, 7]]
Tim
  • 37
  • 2
  • 6

4 Answers4

2

the issue here as other explained is that int objects are immutable So doing

two[0][0] = 9

wont change the old two[0][0] object instead it will create new object and make two[0][0] reference this new object (the old object is garbage collected if not other reference it in this case there is)

and to be more clear in this case after creating both arrays we have the following (--> means reference)

one[0][0] --> object(1)
two[0][0] --> object(1)

then when you excuted

two[0][0] = 9

the object reference looks like this

one[0][0] --> object(1)
two[0][0] --> object(9)

So to solve this we need to change the values that you have in the array to be mutable

I have created very simple class that hold the int and made the array out of it and that resolves your issue

here is working code

class IntHolder:
    def __init__(self,int_value):
        self.intvalue = int_value
    def set_value(self,int_value):
        self.intvalue = int_value
    def __str__(self):
        return str(self.intvalue)
    def __repr__(self):
        return str(self.intvalue)
    def __str__(self):
        return str(self.intvalue)
one = [
    [IntHolder(1), IntHolder(2), IntHolder(3), IntHolder(4)],
    [IntHolder(2), IntHolder(3), IntHolder(4), IntHolder(5)],
    [IntHolder(3), IntHolder(4), IntHolder(5), IntHolder(6)],
    [IntHolder(4), IntHolder(5), IntHolder(6), IntHolder(7)]
    ]

two = [
    [one[0][0], one[0][1], one[1][0], one[1][1]],
    [one[0][2], one[0][3], one[1][2], one[1][3]],
    [one[2][0], one[2][1], one[3][0], one[3][1]],
    [one[2][2], one[2][3], one[3][2], one[3][3]]
    ]
two[0][0].set_value(9)

print one
print two
Hani
  • 1,354
  • 10
  • 20
1

Integers are immutable in python. One approach you can take is to enclose the integers in a container type (list) and modify the container values.

See these additional pointers for related details:

Python passing an integer by reference

How do I pass a variable by reference?

Community
  • 1
  • 1
Forhad Ahmed
  • 1,761
  • 13
  • 18
0

You're actually copying the values.

Copy the reference to the lists in one:

two=[one[0], one[1], one[2], one[3]]

Then you get for two[0][0]=9:

one == [[9, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7]]
two == [[9, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7]]
allo
  • 3,955
  • 8
  • 40
  • 71
  • 2
    This answer changes the structure of the list `two`. It just happens to give the same output for this specific set of numbers. Note that the OP's original `two` is divided into four "quadrants" that contain the numbers from `one[0], one[1], one[2], one[3]` , not four lines. – Keiwan Jul 03 '16 at 16:26
  • Indeed, i did not saw what the indices are exactly doing. Then i would suggest writing a wrapper class, where ``__getitem__`` returns the correct value from the list ``one``. May be the easiest and most flexible way, with respect to larger matrices in the future. – allo Jul 04 '16 at 12:23
0

Is this what you're trying to accomplish?

def listfix(one, two):
    if one != two:
        one = two
    return one, two

two[0][0]=9
one, two = listfix(one, two)
act123
  • 5
  • 1