Почему python печатает странные результаты при использовании вложенного цикла здесь?

#python #arrays #loops #nested-loops

#python #массивы #циклы #вложенные циклы

Вопрос:

Мне был предоставлен массив строк, и я хочу разделить каждую из отдельных строк на отдельные символы и сохранить их в отдельном 2-D массиве. Я написал следующий код:-

 # The given array
grid = ['1112', '1912', '1892', '1234']

# Creating a new 2D array
mat = [[None]*len(grid)]*len(grid)
for i in range(0,len(grid)):
    for j in range(0,len(grid)):
        mat[i][j] = grid[i][j]
print(mat)
 

Но это дает странные значения в моем двумерном массиве, mat. Каждая строка 2D массива mat печатается как [‘1′,’2′,’3′,’4’] но это должно быть значение только последней строки.

Я буду благодарен, если кто-нибудь сможет ответить на мой запрос.

Ответ №1:

 mat = [[None]*len(grid)]*len(grid)
 

Этот оператор создает реляционный 2D-массив (матрицу), поэтому всякий раз, когда вы обновляете строку, он обновляет все остальные строки.

Вы должны использовать это для создания пустого 2D-массива:

 mat = [[None for i in len(grid)] for j in range(len(grid))]
 

Как прокомментировал @marc, вы также можете передать одно понимание списка как width = height здесь

 mat = [[None]*len(grid) for _ in range(len(grid))]
 

Комментарии:

1. Вы можете смело пропустить один из шагов понимания списка и использовать mat = [[None]*len(grid) for i in range(len(grid)] .

2. @Marc Ах да, я добавлю это вместе, если позже им понадобится матрица с шириной, отличной от высоты, им все равно нужно будет выполнить 2 понимания списка

Ответ №2:

Умножение в список создает ту же ссылку в памяти, код исправлен следующим образом:

 # The given array
grid = ['1112', '1912', '1892', '1234']

# Creating a new 2D array
# mat = [[None]*len(grid)]*len(grid)
mat = []
for i in range(len(grid)):
    t = []
    for j in range(len(grid)):
        t.append(None)
    mat.append(t)

for i in range(0,len(grid)):
    for j in range(0,len(grid)):
        mat[i][j] = grid[i][j]
print(mat)
 

Комментарии:

1. Это сработало бы, но требует больше времени для обработки, чем мой ответ, с пониманием списка, который также более удобочитаем

Ответ №3:

Я должен согласиться, что в этой проблеме легко запутаться.

Допустим len(grid) , = 2, поэтому мы получаем mat = [[None]*2]*2

Здесь mat[0] указывает на тот же pobject of mat[1] , потому *2 что дает два указателя, которые указывают на один и тот же массив. Вместо этого вы можете использовать for _ in range(2) для создания двух разных объектов — [[None]*len(grid) for _ in range(len(grid))]

Мы можем использовать id для печати адреса объекта для проверки:

 >>> mat = [[None]*2]*2
>>> id(mat[0])
76447616
>>> id(mat[1])
76447616
>>> grid = [0, 0]
>>> x = [[None]*len(grid) for _ in range(len(grid))]
>>> id(x[0])
76457744
>>> id(x[1])
76391968