Заполните фиктивную матрицу с помощью словарных ключей - PullRequest
0 голосов
/ 21 октября 2018

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

У меня есть двумерная фиктивная матрица, которую я создаю так:

self.matrix = [[0] * self.length] * self.length

, который создает матрицу N x N в зависимости от длины

У меня также есть отсортированный список узлов, которые имеют имена (= ключи), и я хочу сопоставить эти имена с индексами (= значения) 0..N

self.data = dict(zip(self.nodes, self.index_array))

Все это прекрасно работает до тех пор, пока я не попытаюсь заполнить мою фиктивную матрицу смежности "1" для Ni, соединенного с Nj.«ребра» - это список кортежей :dge = [("u1", "v1"), ("u1", "v2"), ..., ("ui", "uj")]

for row in edges:
    self.matrix[self.data[row[0]]][self.data[row[1]]] = 1

Теперь, когда я запускаю описанный выше метод, я получаю матрицу, которая полна единиц, когда должны быть только единицы для каждого соединения между узлом u и узлом v


Я попытался смоделировать этопроблема в меньшей степени, и здесь это работает отлично!Я не знаю, что происходит.

a = {"3": 0, "4": 1, "5": 2}
edges = [("3", "5"), ("4", "3"), ("5", "3")]
nodes = ["3", "4", "5"]
index = [0, 1, 2]

data = dict(zip(nodes, index))

matrix = [[0, 0, 0],
          [0, 0, 0],
          [0, 0, 0]]

for row in edges:
    matrix[data[row[0]]][data[row[1]]] = 1

print(a)
print(data)
print(matrix)

Ответы [ 2 ]

0 голосов
/ 21 октября 2018

Это не создает матрицу правильно:

self.matrix = [[0] * self.length] * self.length

Использование:

self.matrix = [[0] * self.length for _ in range(self.length)]

Причина умножения списка создает кратные ссылки в списке, поэтому каждая строкассылка на тот же список в исходном коде.

Вот пример различия:

>>> A = [[0] * 3] * 3
>>> A
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> A [0][0] = 1
>>> A
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]

Обратите внимание, как все три строки измененоЭто связано с тем, что каждая строка содержит копию того же списка :

>>> A = [[0] * 3 for _ in range(3)]
>>> A
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> A[0][0] = 1
>>> A
[[1, 0, 0], [0, 0, 0], [0, 0, 0]]

Теперь для каждой строки создается новая строка из трех нулей.Изменение одного элемента в строке не приводит к изменению всех строк.

Обратите внимание, что [0] * 3 также дублирует ссылки на целое число ноль.Будучи неизменным объектом, это не проблема, но если у вас есть изменяемый объект, вам не нужны три копии.Вы бы использовали [mutable_obj() for _ in range(3)] для создания 3 различных объектов, поэтому, если вы редактируете один, остальные не изменятся.

0 голосов
/ 21 октября 2018

Используя оператор * в списке подсписков, вы повторяете те же ссылки на подсписки, поэтому любое изменение, внесенное в подсписок, будет отражаться на всех других элементах, содержащих ту же ссылку на подсписок.

Вы можете инициализировать self.matrix с использованием понимания списка:

self.matrix = [[0] * self.length] for _ in range(self.length)]
...