2

嘿,我正在编写一个函数,它接受一个矩阵输入,例如下面的一个并返回它的逆矩阵,其中所有的 1 都更改为 0,所有的 0 都更改为 1,同时保持从左上角到右下角的对角线为 0。



示例输入:

g1 = [[0, 1, 1, 0],
     [1, 0, 0, 1],
     [1, 0, 0, 1],
     [0, 1, 1, 0]]



该函数应输出以下内容:

g1 = [[0, 0, 0, 1],
     [0, 0, 1, 0],
     [0, 1, 0, 0],
     [1, 0, 0, 0]]



当我运行该程序时,它会引发“列表索引超出范围”错误。我确定这是因为我设置的循环试图访问不存在的值,但是我如何允许输入未知的行和列大小?我只知道如何使用单个列表来执行此操作,但是列表列表?这是函数,不包括调用它的测试函数:

def inverse_graph(graph):
    # take in graph
    # change all zeros to ones and ones to zeros

    r, c = 0, 0 # row, column equal zero

    while (graph[r][c] == 0 or graph[r][c] == 1): # while the current row has a value.
        while (graph[r][c] == 0 or graph[r][c] == 1): # while the current column has a value
            if (graph[r][c] == 0):
                graph[r][c] = 1
            elif (graph[r][c] == 1):
                graph[r][c] = 0
            c+=1
        c=0
        r+=1

    c=0
    r=0

    # sets diagonal to zeros

    while (g1[r][c] == 0 or g1[r][c] == 1):
        g1[r][c]=0
        c+=1
        r+=1

    return graph
4

5 回答 5

1

这并不能直接回答您的问题,但我想指出,在 Python 中,您通常可以通过使用
    for <element> in <container>:
语句来减少甚至有时消除使用索引的需要。通过与内置enumerate()函数一起使用,可以同时获取索引和对应的元素
    for <index>,<element> in enumerate(<container>):

将它们应用于您的问题将允许这样的事情:

g1 = [[0, 1, 1, 0],
      [1, 0, 0, 1],
      [1, 0, 0, 1],
      [0, 1, 1, 0]]

def inverse_graph(graph):
    """ invert zeroes and ones in a square graph
        but force diagonal elements to be zero
    """
    for i,row in enumerate(graph):
        for j,cell in enumerate(row):
            row[j] = 0 if cell or i == j else 1
    return graph

print(g1)
print(inverse_graph(g1))

输出:

[[0, 1, 1, 0], [1, 0, 0, 1], [1, 0, 0, 1], [0, 1, 1, 0]]
[[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]]

哪个更简单,也更有效。另一点是,由于您将该函数应用于可变(可变)容器,列表列表,因此实际上不需要返回容器,因为它正在就地更改。这样做并没有错,因为它可以使函数的使用变得更容易,但这是您可能没有意识到的。

您可以通过使用称为 a 的东西来进一步缩短函数并完全消除索引list comprehension

def inverse_graph(graph):
    return [[0 if cell or i == j else 1
                for j,cell in enumerate(row)]
                    for i,row in enumerate(graph)]

由于它们的工作方式,此版本不会就地更改图形,而是创建并返回一个新图形。

于 2012-12-08T22:53:43.033 回答
0
while (graph[r][c] == 0 or graph[r][c] == 1): # while the current row has a value.

在将其 -possible- 值与 0 或 1 进行比较之前,您必须首先确保两个索引都存在。这会导致您的异常。要反转矩阵,您需要执行类似的操作

for row in graph:
    for idx, v in enumerate (row):
        row [idx] = 0 if v else 1
于 2012-12-08T22:25:58.527 回答
0

错误在于您的“当前行有值”。当您遍历行中的元素时,这将始终是正确的,当您越过它们时,您将得到异常。

相反,使用:

for r in range(len(graph):
    for c in range(len(graph[0]):
        # do something with graph[r][c]
于 2012-12-08T22:26:27.917 回答
0

这相当简单。基本上你需要找到数组中元素的数量

 mylist = [1,2,3,4,5]
 len(mylist) # returns 5
 #this gives the number of elements.
 rows=len(g1) # get the number of rows
 columns=len(g1[0]) #get the number of columns
 #Now iterate over the number of rows and columns
 for r in range(0, rows):
    for c in range (0,columns):
       if (r==c):
              g1[r][c]=0
       else:
           g1[r][c]=1-g1[r][c]

希望有帮助

于 2012-12-08T22:28:13.580 回答
0

不是您问题的答案,但这是一种“简单”的方法

return [[0 if i2==i else 1 if item == 0 else 0 for i2,item in enumerate(row)] for i,row in graph]

于 2012-12-08T22:30:33.487 回答