在嵌套列表中对角线列出元素

9
这是我的第一篇帖子,我是这个很棒的网站的新手。
我想将3x3数组中所有元素按对角线列出:
L = [  [1, 2, 3],
       [4, 5, 6],
       [7, 8, 9] ]

预期输出:

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

此外,如何将其推广到任意N x N数组?
编辑:我注意到这个问题之前已经被问过了,但是我想找一种不导入numpy或任何库的方法。
编辑2:我的一个同学提供了这个解决方案,我最喜欢它:
由于您从左下角开始查找对角线,因此可以通过从正方形的右上角开始并在最后反转您的解决方案来完成此操作。我的方法是首先翻转L中的每一行,然后将每个元素附加到其相应的对角线列表中。这里的见解是您开始在每行K中附加元素,而不是在最终列表的第一个子列表中,而是从indice K开始。例如,在将行[4,5,6]反转为行[6,5,4]之后,我将6附加到我的对角线排序列表的第二个子列表中(因为这是第二行),然后我将5附加到第三个子列表中,然后我将4附加到第四个子列表中。但是,如果我此时没有第四个子列表,我将添加第四个空列表,然后用4填充它。
我的解释可能不太清楚,所以这是我有的代码。
def diagonal(l):

    L = l[:]
    return_list = [[] for i in range(len(L))]

    for line in range(len(L)):
        L[line].reverse()
        i = line

        for elem in L[line]:
            if i >= len(return_list):
                return_list.append([])

            return_list[i].append(elem)
            i += 1

    return_list.reverse()
    return return_list

我之前为一个程序想出了一种不使用numpy的方法来实现这个功能。我会将它添加到https://dev59.com/BW015IYBdhLWcg3w7wMW。 - flakes
1
@Calpratt 谢谢!我不得不读你的解决方案三次才理解,但最终我懂了;D - Moe
1个回答

15

仅使用Python(不使用NumPy):

import itertools as IT

L = [  [1, 2, 3],
       [4, 5, 6],
       [7, 8, 9] ]
N = len(L)
d = dict()
for i,j in IT.product(range(N), repeat=2):
    d.setdefault(j-i, []).append((i,j))

print([[L[i][j] for i,j in d[k]] for k in range(-N+1, N)])    
# [[7], [4, 8], [1, 5, 9], [2, 6], [3]]
或者更好的方法是使用Nemo的转换(广义到 x 形状的矩阵):链接

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

h, w = len(L), len(L[0])

print([[L[h-1-q][p-q]
        for q in range(min(p, h-1), max(0, p-w+1)-1, -1)]
       for p in range(h+w-1)])                             
# [[7], [4, 8], [1, 5, 9], [2, 6], [3]]
我们还可以将这段代码放入一个函数中,以便更方便地使用:
def diagonals(L):
    """
    https://stackoverflow.com/a/31373955/190597 (unutbu)
    >>> L = array([[ 0,  1,  2],
                   [ 3,  4,  5],
                   [ 6,  7,  8],
                   [ 9, 10, 11]])

    >>> diagonals(L)
    [[9], [6, 10], [3, 7, 11], [0, 4, 8], [1, 5], [2]]
    """
    h, w = len(L), len(L[0])
    return [[L[h - p + q - 1][q]
             for q in range(max(p-h+1, 0), min(p+1, w))]
            for p in range(h + w - 1)]


def antidiagonals(L):
    """
    >>> L = array([[ 0,  1,  2],
                   [ 3,  4,  5],
                   [ 6,  7,  8],
                   [ 9, 10, 11]])

    >>> antidiagonals(L)
    [[0], [3, 1], [6, 4, 2], [9, 7, 5], [10, 8], [11]]
    """
    h, w = len(L), len(L[0])
    return [[L[p - q][q]
             for q in range(max(p-h+1,0), min(p+1, w))]
            for p in range(h + w - 1)]

很棒的答案。在对角线上执行所需操作后,我该如何将矩阵转换回原始形式(对角线->矩阵)? - bimbi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接