代码之家  ›  专栏  ›  技术社区  ›  Primusa

检查嵌套列表中对角线的Pythonic方法

  •  2
  • Primusa  · 技术社区  · 7 年前

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

    我想看看有没有对角的。嵌套列表可以有任何大小,只要子列表的长度等于整个列表的长度(它是一个正方形)。因此,如果我在上面的列表中运行它,它将返回False,因为两个1是对角的。

    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
    

    代码扫描列表1s,当找到一个时,它会查看列表的四个角并进行搜索。它继续沿角点方向搜索,每次移动一个网格。如果找到另一个1,则返回false。一旦搜索了所有可能的对角网格(直到返回索引错误),代码将移动到找到的下一个1。搜索每个1后,如果没有找到任何对角线,则代码返回true。

    它感觉既笨重又低效,但我不知道如何压缩它。有没有较短的方法?

    4 回复  |  直到 7 年前
        1
  •  4
  •   Ajax1234    7 年前

    您可以这样访问对角线:

    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
    
        2
  •  2
  •   Paul Cornelius    7 年前

    你可以先想一个命名对角线的方法。例如,在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)
    

    这提出了一种有效的算法,用于确定任意两个“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
    
        3
  •  1
  •   hys    7 年前

    你可以用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))