Получить все диагонали в матрице / списке списков в Python

Я ищу Pythonic способ получить все диагонали (квадратной) матрицы, представленные в виде списка списков.

Предположим, что у меня есть следующая матрица:

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

Тогда большие диагонали легки:

 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] 

Но у меня проблемы с созданием всех диагоналей. Результат, который я ищу, это:

 [[-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]] 

  • Flask-login AttributeError: объект 'Пользователь' не имеет атрибута 'is_active'
  • Извлечение объекта модуля из кадра стека
  • флажок-кеш memoize параметры строки запроса URL-адреса также
  • Распечатайте весь код в скрипте Python
  • Углы между двумя n-мерными векторами в Python
  • Рамка для бутылок - как остановить?
  • Получить вершины на LineString по обе стороны точки
  • Ошибка импорта в программе приветствия python
  • 6 Solutions collect form web for “Получить все диагонали в матрице / списке списков в Python”

    Есть, вероятно, лучшие способы сделать это в 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]] 

    Изменить : обновлено для обобщения для любого размера матрицы.

     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]] 

    Начните с диагоналей, наклонных вверх-вниз.

    Если (x, y) – прямоугольная координата внутри матрицы, вы хотите преобразовать ее в / из координатной схемы (p, q), где p – номер диагонали, а q – индекс по диагонали. (Таким образом, p = 0 – диагональ [-2], p = 1 – диагональ [9,5], p = 2 – диагональ [3, -6,3] и т. Д.)

    Чтобы преобразовать a (p, q) в (x, y), вы можете использовать:

     x = q y = p - q 

    Попробуйте подключить значения p и q, чтобы увидеть, как это работает.

    Теперь вы просто петли … Для p от 0 до 2N-1 и q от max (0, p-N + 1) до min (p, N-1). Преобразуйте p, q в x, y и распечатайте.

    Затем для других диагоналей повторите петли, но используйте другое преобразование:

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

    (Это просто просто переворачивает матрицу влево-вправо.)

    Извините, я на самом деле не кодировал это в Python. 🙂

    Это для Moe , который задал аналогичный вопрос .

    Я начинаю с простых функций для копирования строк или столбцов любой прямоугольной матрицы.

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

    С помощью этих двух функций я получаю диагонали, добавляя увеличивающийся / уменьшающийся буфер к началу / концу каждой строки. Затем я получаю столбцы этой буферизованной сетки, а затем удаляю буфер по каждому столбцу. то есть)

     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.

     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 

    Из диаграммы видно, что каждая диагональ и ось однозначно идентифицируются с использованием этих уравнений. Возьмите каждый уникальный номер из каждой таблицы и создайте контейнер для этого идентификатора.

    Обратите внимание, что обратные диагонали смещены, чтобы начинаться с нулевого индекса и что длина передних диагоналей всегда равна длине обратных диагоналей.

     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]] 

    В последнее время я решил изобретать это колесо. Вот простой способ повторного использования / расширения, чтобы найти диагонали в квадратных списках списков:

     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 (по умолчанию), возвращает диагонали от нижнего левого до верхнего правого, т.е.

     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 , возвращает диагонали от нижнего левого до верхнего правого, т.е.

     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.

    Это работает только для матриц одинаковой ширины и высоты. Но это также не зависит от третьих сторон.

     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) 
    Python - лучший язык программирования в мире.