0

I did a for loop using enumerate from values in a matrix and tried assigning a value to the items that are different than 0 while appending to a list elements that are equal to 0. The fact is that original matrix don't get updated.

Sample code:

matrix = [[0, 0, 0], [0, 1, 0], [1, 1, 1]]
current = []
for x, i in enumerate(matrix):
    for y, j in enumerate(i):
        if j == 0:
            current.append((x, y))
        else:
            #matrix[x][y] = -1 # This works
            j = -1 # This doesn't

Since this doesn't work, there is no utility in using enumerate for that case. So I changed the code to:

matrix = [[0, 0, 0], [0, 1, 0], [1, 1, 1]]
current = []
for x in range(len(matrix)):
    for y in range(len(matrix[0])):
        if matrix[x][y] == 0:
            current.append((x, y))
        else:
            matrix[x][y] = -1

The code above IMO is much less readble and also pylint suggests against using that with:

C0200: Consider using enumerate instead of iterating with range and len (consider-using-enumerate)

staticdev
  • 2,950
  • 8
  • 42
  • 66
  • The fact that you're attempting to accumulate a new list while also altering the original at the same time is going to limit how nice this can be. I'd use a list comprehension/generator expression here, but that would require some extra iteration. How much of a concern is performance? – Carcigenicate Oct 13 '19 at 14:43
  • @Carcigenicate I have a constraint that I need to see the items in the matrix just once. – staticdev Oct 13 '19 at 14:45
  • 1
    I think you're probably stuck with the second solution then. Not every problem has a beautiful solution. Linter warnings are good suggestions, not hard rules. – Carcigenicate Oct 13 '19 at 14:49

1 Answers1

1

You can't just update 2d array in-place through assigning to local variable j = -1 (which is reinitialized on each loop iteration for y, j in enumerate(i)).

In your simple case you can update your matrix with the following simple traversal:

matrix = [[0, 0, 0], [0, 1, 0], [1, 1, 1]]
for i, row in enumerate(matrix):
    for j, val in enumerate(row):
        if val != 0: matrix[i][j] = -1

print(matrix)    # [[0, 0, 0], [0, -1, 0], [-1, -1, -1]]

Though Numpy provides a more powerful way for updating matrices:

import numpy as np

matrix = np.array([[0, 0, 0], [0, 1, 0], [1, 1, 1]])
matrix = np.where(matrix == 0, matrix, -1)

print(matrix)
RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105
  • Yes, that is exactly how I put in my example. See: `#matrix[x][y] = -1 # This works`. But why does `j = -1` doesn't work? Isn't there a cleaner solution for that? – staticdev Oct 13 '19 at 14:48
  • also note that I need to update `current` list at the same time. – staticdev Oct 13 '19 at 14:51
  • 1
    @StaticX `j = -1` doesn't work because `j` is just a local variable. `j = -1` just changes what `j` points to. If you have `x = 1; y = x; x = 2;`, `y` would still be equal to `1`. – Carcigenicate Oct 13 '19 at 14:51
  • @StaticX, as was mentioned, you are trying to update 2d array in-place via local variable `j = -1` - that's simply wrong – RomanPerekhrest Oct 13 '19 at 14:54