按对角线列出嵌套列表中的元素
这是我第一次发帖,我对这个很棒的网站还很陌生。
我想要把一个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:我的一位同学提供了这个解决方案,我觉得这个方法最好:
因为你是从左下角开始找对角线的,所以可以从右上角开始,然后最后再反转你的结果。我的方法是先把每一行反转,然后把每个元素添加到对应的对角线列表中。这里的关键是,在每一行K中,你不是从最终列表的第一个子列表开始添加元素,而是从索引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
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的变换(可以推广到 h x w
形状的矩阵):
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)]