2017-09-22 88 views
0

Python的方式我有0和的如的嵌套列表:檢查對角線嵌套列表

L = [[1, 0, 1], 
    [0, 0, 0], 
    [0, 0, 1]] 

我要檢查是否有任何的有彼此成對角。只要子列表的長度等於整個列表的長度(這是一個正方形),嵌套列表的大小就可以是任意大小。所以如果我在上面的列表中運行它,它會返回False,因爲兩個是對角的。

我當前的代碼是:

for num, i in enumerate(List): 
    for count, m in enumerate(i): 
     key1 = True 
     key2 = True 
     key3 = True 
     key4 = True 
     num1 = num 
     num2 = num 
     num3 = num 
     num4 = num 
     count1 = count 
     count2 = count 
     count3 = count 
     count4 = count 
     if m == 1: 
      while key1 or key2 or key3 or key4: 
      #print(key1, key2, key3, key4) 
       try: 
        if List[num1 + 1][count1 + 1] == 1: 
         print(List[num1 + 1][count1 + 1]) 
         return False 
        num1 += 1 
        count1 += 1 
       except IndexError: 
        key1 = False 
       try: 
        if List[num2 - 1][count2 + 1] == 1: 
         if num2 > 0: 
          print(List[num2 - 1][count2 + 1]) 
          return False 
        num2 -= 1 
        count2 += 1 
       except IndexError: 
         key2 = False 
       try: 
        if List[num3 + 1][count3 - 1] == 1: 
         if count3 > 0: 
          print(List[num3 + 1][count3 - 1]) 
          print(num3 + 1, count3 - 1) 
          return False 
        num3 += 1 
        count3 -= 1 
       except IndexError: 
        key3 = False 
       try: 
        if List[num4 - 1][count4 - 1] == 1: 
         if count4 > 0 and num4 > 0: 
          print(List[num4 - 1][count4 - 1]) 
          return False 
        num4 -= 1 
        count4 -=1 
       except IndexError: 
        key4 = False 
return True 

代碼掃描列表1秒,而當發現一個,它看起來在其四角和搜索他們。它繼續搜索角落的方向,一次移動一個網格。如果找到另一個1,則返回false。一旦搜索到所有可能的對角網格(直到返回索引錯誤),代碼就會移到找到的下一個1。一旦搜索到每一個1並且沒有發現任何對角線,代碼就會返回true。

它感覺笨重和低效,但我不知道如何壓縮它。有沒有更簡單的方法來做到這一點?

回答

3

您可以訪問對角線像這樣:

L = [[1, 0, 1], 
[0, 0, 0], 
[0, 0, 1]] 

diag1 = [L[i][i] for i in range(len(L))] 
diag2 = [L[i][len(L[0])-i-1] for i in range(len(L))] 
if diag1 == diag2: 
    pass #do something here 
+0

對不起,我應該在問題中進一步澄清。我的意思是對角線和所有對角線一樣。在一個棋盤上畫一個主教,並把它移動到哪裏。對於列表中的每個個體1,我想分析與該對角線1對應的所有網格的集合。 – Primusa

1

可以使用numpy的解決這個問題。

import numpy as np 
 
def diagonal(arr): 
 
    d = np.diag(a) 
 

 
    set_len = len(set(d)) 
 
    d_len = len(d) 
 
    if set_len < d_len: 
 
     return False 
 
    else: 
 
     return True 
 

 
a = np.array([[1, 0, 1], [0, 0, 0], [0, 0, 1]]) 
 
print(diagonal(a))

1

您可以從思考命名對角線的方法開始。例如,在一個3x3矩陣指數(X,Y)是這樣的:

(0,0) (1,0) (2,0) 
(0,1) (1,1) (2,1) 
(0,2) (1,2) (2,2) 

如果我們按照對角線,它們的指數有一個簡單的模式。那到右上角運行左下方的對角線:

Diag #1 (0,0) 
Diag #2 (0,1) (1,0) 
Diag #3 (0,2) (1,1) (2,0) 
Diag #4 (1,2) (2,1) 
Diag #5 (2,2) 

從左上角到右下角,他們是:

#1 (0,2) 
#2 (0,1) (1,2) 
#3 (0,0) (1,1) (2,2) 
#4 (1,0) (2,1) 
#5 (2,0) 

注意,在左下到右上的情況下,每一個細胞(X, y)在相同的對角線上具有相同的x + y值。在另一種情況下,同一對角線上的每個單元格都具有相同的x - y值。很顯然,對於任何大小的矩陣都是如此。我們可以使用x + y和x-y來命名單個對角線。當我們遍歷矩陣時,每遇到一個「1」,我們就可以立即計算出與之相交的兩條對角線的名稱。

這表明一個有效的算法來決定是否有任何兩個「1」在同一對角線上。在Python中,我們可以使用兩組來跟蹤「佔用」對角線。如果我們在已佔用的對角線上遇到「1」,則返回True,否則返回false。只要我們訪問所有元素,我們就可以按照任意順序遍歷矩陣。

def has_diagonal_ones(a): 
    # a is a 2-dimensional square array of 0's and 1's 
    lower_left_upper_right = set() 
    upper_left_lower_right = set() 
    for x in range(len(a)): 
     for y in range(len(a)): 
      if a[x][y] == 0: 
       continue 
      i_lower_to_upper = x + y 
      i_upper_to_lower = x - y 
      if i_lower_to_upper in lower_left_upper_right: 
       return True 
      if i_upper_to_lower in upper_left_lower_right: 
       return True 
      lower_left_upper_right.add(i_lower_to_upper) 
      upper_left_lower_right.add(i_upper_to_lower) 
    return False 

L = [[1, 0, 1], 
[0, 0, 0], 
[0, 0, 1]] 
print(has_diagonal_ones(L)) 

>>> True