在Python中获取matrix/列表中的所有对angular线

我正在寻找Pythonic的方式来获取(方形)matrix的所有对angular线,表示为列表的列表。

假设我有以下matrix:

matrix = [[-2, 5, 3, 2], [ 9, -6, 5, 1], [ 3, 2, 7, 3], [-1, 8, -4, 8]] 

那么大对angular线很容易:

 l = len(matrix[0]) print [matrix[i][i] for i in range(l)] # [-2, -6, 7, 8] print [matrix[l-1-i][i] for i in range(l-1,-1,-1)] # [ 2, 5, 2, -1] 

但是我很难想出一个方法来生成所有的对angular线。 我正在寻找的输出是:

 [[-2], [9, 5], [3,-6, 3], [-1, 2, 5, 2], [8, 7, 1], [-4, 3], [8], [2], [3,1], [5, 5, 3], [-2, -6, 7, 8], [9, 2, -4], [3, 8], [-1]] 

在numpy中可能有更好的方法比下面更好,但我还不太熟悉它:

 import numpy as np matrix = np.array( [[-2, 5, 3, 2], [ 9, -6, 5, 1], [ 3, 2, 7, 3], [-1, 8, -4, 8]]) diags = [matrix[::-1,:].diagonal(i) for i in range(-3,4)] diags.extend(matrix.diagonal(i) for i in range(3,-4,-1)) print [n.tolist() for n in diags] 

产量

 [[-2], [9, 5], [3, -6, 3], [-1, 2, 5, 2], [8, 7, 1], [-4, 3], [8], [2], [3, 1], [5, 5, 3], [-2, -6, 7, 8], [9, 2, -4], [3, 8], [-1]] 

编辑 :更新来推广任何matrix大小。

 import numpy as np # Alter dimensions as needed x,y = 3,4 # create a default array of specified dimensions a = np.arange(x*y).reshape(x,y) print a print # a.diagonal returns the top-left-to-lower-right diagonal "i" # according to this diagram: # # 0 1 2 3 4 ... # -1 0 1 2 3 # -2 -1 0 1 2 # -3 -2 -1 0 1 # : # # You wanted lower-left-to-upper-right and upper-left-to-lower-right diagonals. # # The syntax a[slice,slice] returns a new array with elements from the sliced ranges, # where "slice" is Python's [start[:stop[:step]] format. # "::-1" returns the rows in reverse. ":" returns the columns as is, # effectively vertically mirroring the original array so the wanted diagonals are # lower-right-to-uppper-left. # # Then a list comprehension is used to collect all the diagonals. The range # is -x+1 to y (exclusive of y), so for a matrix like the example above # (x,y) = (4,5) = -3 to 4. diags = [a[::-1,:].diagonal(i) for i in range(-a.shape[0]+1,a.shape[1])] # Now back to the original array to get the upper-left-to-lower-right diagonals, # starting from the right, so the range needed for shape (x,y) was y-1 to -x+1 descending. diags.extend(a.diagonal(i) for i in range(a.shape[1]-1,-a.shape[0],-1)) # Another list comp to convert back to Python lists from numpy arrays, # so it prints what you requested. print [n.tolist() for n in diags] 

产量

 [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] [[0], [4, 1], [8, 5, 2], [9, 6, 3], [10, 7], [11], [3], [2, 7], [1, 6, 11], [0, 5, 10], [4, 9], [8]] 

从倾斜的对angular线开始。

如果(x,y)是matrix内的直angular坐标,则要转换为坐标scheme(p,q),其中p是对angular线的编号,q是沿对angular线的索引。 (所以p = 0是[-2]对angular线,p = 1是[9,5]对angular线,p = 2是[3,-6,3]对angular线等)。

要将(p,q)转换为(x,y),可以使用:

 x = q y = p - q 

尝试插入p和q的值,看看这是如何工作的。

现在你只是循环…对于从0到2N-1的p和从max(0,p-N + 1)到min(p,N-1)的q。 将p,q转换为x,y并打印。

然后对于其他对angular线,重复循环,但使用不同的转换:

 x = N - 1 - q y = p - q 

(这实际上只是将matrix左右翻转。)

对不起,我实际上没有用Python编写这个代码。 🙂

这是Moe ,他问了一个类似的问题 。

我首先通过简单的函数来复制任何矩形matrix的行或列。

 def get_rows(grid): return [[c for c in r] for r in grid] def get_cols(grid): return zip(*grid) 

有了这两个函数,我可以通过在每一行的开始/结尾添加一个递增/递减缓冲区来获得对angular线。 然后我得到这个缓冲网格的列,然后删除每列的缓冲区。 即)

 1 2 3 |X|X|1|2|3| | | |1|2|3| 4 5 6 => |X|4|5|6|X| => | |4|5|6| | => [[7],[4,8],[1,5,9],[2,6],[3]] 7 8 9 |7|8|9|X|X| |7|8|9| | | 

 def get_backward_diagonals(grid): b = [None] * (len(grid) - 1) grid = [b[i:] + r + b[:i] for i, r in enumerate(get_rows(grid))] return [[c for c in r if not c is None] for r in get_cols(grid)] def get_forward_diagonals(grid): b = [None] * (len(grid) - 1) grid = [b[:i] + r + b[i:] for i, r in enumerate(get_rows(grid))] return [[c for c in r if not c is None] for r in get_cols(grid)] 

我遇到了另一个有趣的解决这个问题。 通过查看x和y的组合,可以立即发现行,列,前向和后向对angular线。

 Row = x Column = y F-Diag = x+y B-Diag = xy B-Diag` = -MIN+xy | 0 1 2 | 0 1 2 | 0 1 2 | 0 1 2 | 0 1 2 --|--------- --|--------- --|--------- --|--------- --|--------- 0 | 0 1 2 0 | 0 0 0 0 | 0 1 2 0 | 0 1 2 0 | 2 3 4 1 | 0 1 2 1 | 1 1 1 1 | 1 2 3 1 |-1 0 1 1 | 1 2 3 2 | 0 1 2 2 | 2 2 2 2 | 2 3 4 2 |-2 -1 0 2 | 0 1 2 

从图中可以看出,每个对angular线和轴线都可以使用这些方程唯一标识。 从每个表中取出每个唯一编号,并为该标识符创build一个容器。

请注意,后向对angular线已经被偏移以从零开始,并且前向对angular线的长度总是等于后向对angular线的长度。

 test = [[1,2,3],[4,5,6],[7,8,9],[10,11,12]] max_col = len(test) max_row = len(test[0]) cols = [[] for i in range(max_col)] rows = [[] for i in range(max_row)] fdiag = [[] for i in range(max_col + max_row - 1)] bdiag = [[] for i in range(len(fdiag))] min_bdiag = -max_col + 1 for y in range(max_col): for x in range(max_row): cols[y].append(test[y][x]) rows[x].append(test[y][x]) fdiag[x+y].append(test[y][x]) bdiag[-min_bdiag+xy].append(test[y][x]) print(cols) print(rows) print(fdiag) print(bdiag) 

哪个会打印

 [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]] [[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]] [[1], [2, 4], [3, 5, 7], [6, 8, 10], [9, 11], [12]] [[10], [7, 11], [4, 8, 12], [1, 5, 9], [2, 6], [3]] 

最近我最终重塑了这个轮子。 这里有一个易于重复使用/扩展的方法来查找正方形列表中的对angular线:

 def get_diagonals(grid, bltr = True): dim = len(grid) assert dim == len(grid[0]) return_grid = [[] for total in xrange(2 * len(grid) - 1)] for row in xrange(len(grid)): for col in xrange(len(grid[row])): if bltr: return_grid[row + col].append(grid[col][row]) else: return_grid[col - row + (dim - 1)].append(grid[row][col]) return return_grid 

假设列表索引:

00 01 02 03

10 11 12 13

20 21 22 23

30 31 32 33

然后设置bltr = True (默认),将对angular线从左下angular返回到右上angular,即

 00 # row + col == 0 10 01 # row + col == 1 20 11 02 # row + col == 2 30 21 12 03 # row + col == 3 31 22 13 # row + col == 4 32 23 # row + col == 5 33 # row + col == 6 

设置bltr = False ,将对angular线从左下angular返回到右上angular,即

 30 # (col - row) == -3 20 31 # (col - row) == -2 10 21 32 # (col - row) == -1 00 11 22 33 # (col - row) == 0 01 12 23 # (col - row) == +1 02 13 # (col - row) == +2 03 # (col - row) == +3 

这是一个使用OP的inputmatrix的可运行版本 。

这只适用于宽度和高度相等的matricies。 但它也不依赖于任何第三方。

 matrix = [[11, 2, 4],[4, 5, 6],[10, 8, -12]] # only works for diagnoals of equal width and height def forward_diagonal(matrix): if not isinstance(matrix, list): raise TypeError("Must be of type list") results = [] x = 0 for k, row in enumerate(matrix): # next diag is (x + 1, y + 1) for i, elm in enumerate(row): if i == 0 and k == 0: results.append(elm) break if (x + 1 == i): results.append(elm) x = i break return results print 'forward diagnoals', forward_diagonal(matrix)