2012-12-08 34 views
2

嘿我写一个函数,它接受一个矩阵输入,例如下面的一个,并返回它的逆,其中所有的1秒被改变为0和所有的0改变为1秒,同时保持从左上角到右下角0s的对角线。蟒矩阵 - 列表索引超出范围



一个例子输入:

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 
+0

我想,如果你花一些时间来学习[list comprehensions](http://www.python.org/dev/peps/pep-0202/),那么你的代码的可读性,正确性和速度会大大提高。 ) – erikbwork

+0

如果你使用了很多矩阵/二维数组,NumPy非常有用。 – ninMonkey

回答

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]] 

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

你可以缩短功能多一点点,完全用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)] 

,因为他们的工作方式,该版本并没有改变就地图,而是创建并返回一个新的。

+0

谢谢!这非常有帮助! – kylecblyth

+0

@martineau我应该提到你的输出并不完全适合这个问题。你最终交换对角元素(应该保持“0”)。否则一个很好的答案。 – IamAlexAlright

+0

@IamAlexAlright:糟糕,我现在纠正的错误。感谢您指出遗漏。希望你仍然认为这是一个很好的答案。 – martineau

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 
0

错误在于“当前行有值时”。当你遍历行中的元素时,这将始终是真实的,当你通过它们时,你会得到异常。

相反,使用:

for r in range(len(graph): 
    for c in range(len(graph[0]): 
     # do something with graph[r][c] 
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] 

希望帮助

0

不回答你的问题,但在这里元素的数目是一个“易”的方式做到这一点

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