【问题标题】:find pattern in matrix made of lists python 3在由列表 python 3 组成的矩阵中查找模式
【发布时间】:2017-05-17 00:27:37
【问题描述】:

我有一个由列表组成的列表,用于创建一个矩阵,其中大部分填充零和其他一些类似这样的数字

a = [[0,0,0,1,0,0,0,0],
     [3,0,0,2,1,0,0,0],
     [3,0,0,0,0,1,0,0],
     [3,5,0,4,0,0,0,0]]

我怎样才能创建一个接受该变量的函数,并找出对角线中是否有重复 3 次的数字?

例如它返回 True 因为 1。 我试图实现这样的功能:

def find_diagonal(matriz):
    for x in range(len(matrix)):
        for for a in range(len(x)):
            if matriz[x][a] != 0:
                encontrar = matriz[x][a]
                if matriz[x+1][a-1] == encontrar:
                    if matriz[x+2][a-2] == encontrar:
                        return True

然后用其他对角线重复if matriz[x][a] != 0 之后的条件(这个寻找指向西南方向的)。

但是除了不是对每个示例都有效(有时它只有效一次,然后停止处理同一个示例),并且在边缘总是会引发索引错误,因为列表会检查顶部的行。

【问题讨论】:

  • 你试过什么? Stack Overflow 不是代码编写服务,您需要提供 minimal reproducible example 来演示您尝试过的内容和发生的事情(以及您想要发生的事情)。作为旁注,由于扩展切片,通常更容易查看您视为 2D 的一维 list 上的对角线。
  • 如果你可以使用numpy,来查找数组中所有对角线的列表,你可以使用:diags = [a[::-1,:].diagonal(i) for i in range(-a.shape[0]+1,a.shape[1])]diags.extend(a.diagonal(i) for i in range(a.shape[1]-1,-a.shape[0],-1))diagsList = [n.tolist() for n in diags]

标签: python list python-3.x function


【解决方案1】:

正如@ShadowRanger 指出的那样,使用扁平列表并使用带有 +/- 1 的 rowlen 步长的切片可能更容易(这会为您提供对角线的项目):

def has_diagonals(listoflist, n=3):
    rowlen = len(listoflist[0])
    numrows = len(listoflist)
    l = [i for row in listoflist for i in row]
    for rownr in range(numrows + 1 - n):
        # Diagonals to the lower right
        for start in range(rowlen + 1 - n):
            lr_diag = l[start+rownr*rowlen::rowlen+1][:n]
            print(lr_diag)
            first = lr_diag[0]
            if first == 0:  # don't check for zero-diagonals
                continue
            if all(item == first for item in lr_diag):  # are all items equal
                print('match', lr_diag)

        # Diagonals to the lower left   
        for start in range(n - 1, rowlen):
            rl_diag = l[start+rownr*rowlen::rowlen-1][:n]
            print(rl_diag)
            first = rl_diag[0]
            if first == 0:  # don't check for zero-diagonals
                continue
            if all(item == first for item in rl_diag):  # are all items equal
                print('match', rl_diag)

我包含了一些 print-calls 我用来可视化内部运作的电话,我认为这些可能会帮助您了解正在发生的事情。带有'match'prints 应替换为return True 或您希望函数返回的任何内容。

可以提高效率,但它应该是正确的(至少对于您的a-matrix)

【讨论】:

    【解决方案2】:

    这个怎么样:

    def check_diag(a, y, x):
      """Take a[y][x] and check if it starts a diagonal"""
      result = False
    
      # We search downwards, there should be at least 2 more rows
      if y > len(a)-2:
        return False
    
      if x < len(a[y])-2:
          # Searching SE direction if possible
          result |= (a[y][x] == a[y+1][x+1] == a[y+2][x+2])
      if x > 1:
          # Searching SW direction if possible
          result |= (a[y][x] == a[y+1][x-1] == a[y+2][x-2])
    
      return result
    
    def has_diag(a):
      # Take all non-zero elements and check if they meet the diag condition
      return any([check_diag(a,y,x)
                    for y in range(len(a))
                    for x in range(len(a[y]))
                    if a[y][x]])
    

    这也会找到更长的对角线,不确定你是否想要。


    编辑:更“残酷”的版本,索引魔法更少:

    def check_diag2(a, y, x):
      """Take a[y][x] and check if it starts a diagonal"""
      try:
        if (a[y][x] == a[y+1][x+1] == a[y+2][x+2]):
          return True
      except IndexError:
        pass
    
      try:
        if (a[y][x] == a[y+1][x-1] == a[y+2][x-2]):
          return True
      except IndexError:
        pass
    
      return False
    

    【讨论】:

    • 有括号时不需要反斜杠。 :)
    • @MSeifert 谢谢,我编辑了答案。也使 if 条件不那么复杂。
    猜你喜欢
    • 2021-06-13
    • 1970-01-01
    • 2017-04-16
    • 2018-09-20
    • 1970-01-01
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多