2012-12-08 78 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]