检查嵌套列表中对角线的 Pythonic 方法
Pythonic way to check diagonals in nested list
我有一个 0 和 1 的嵌套列表,例如:
L = [[1, 0, 1],
[0, 0, 0],
[0, 0, 1]]
我想检查是否有任何对角线。嵌套列表可以有任何大小,只要子列表的长度等于整个列表的长度(它是一个正方形)。因此,如果我 运行 它在上面的列表中,它将 return 错误,因为两个是对角线。
我当前的代码是:
for num, i in enumerate(List):
for count, m in enumerate(i):
key1 = True
key2 = True
key3 = True
key4 = True
num1 = num
num2 = num
num3 = num
num4 = num
count1 = count
count2 = count
count3 = count
count4 = count
if m == 1:
while key1 or key2 or key3 or key4:
#print(key1, key2, key3, key4)
try:
if List[num1 + 1][count1 + 1] == 1:
print(List[num1 + 1][count1 + 1])
return False
num1 += 1
count1 += 1
except IndexError:
key1 = False
try:
if List[num2 - 1][count2 + 1] == 1:
if num2 > 0:
print(List[num2 - 1][count2 + 1])
return False
num2 -= 1
count2 += 1
except IndexError:
key2 = False
try:
if List[num3 + 1][count3 - 1] == 1:
if count3 > 0:
print(List[num3 + 1][count3 - 1])
print(num3 + 1, count3 - 1)
return False
num3 += 1
count3 -= 1
except IndexError:
key3 = False
try:
if List[num4 - 1][count4 - 1] == 1:
if count4 > 0 and num4 > 0:
print(List[num4 - 1][count4 - 1])
return False
num4 -= 1
count4 -=1
except IndexError:
key4 = False
return True
代码扫描列表 1 秒,当找到一个时,它会查看它的四个角并搜索它们。它继续向拐角的方向搜索,一次移动一格。如果找到另一个 1,则 return 为假。一旦搜索了所有可能的对角线网格(最多 returning 索引错误),代码将移动到找到的下一个 1。一旦搜索到每个 1 并且其中 none 找到任何对角线,则代码 return 为真。
感觉笨重且效率低下,但我不确定如何压缩它。有更短的方法吗?
您可以像这样访问对角线:
L = [[1, 0, 1],
[0, 0, 0],
[0, 0, 1]]
diag1 = [L[i][i] for i in range(len(L))]
diag2 = [L[i][len(L[0])-i-1] for i in range(len(L))]
if diag1 == diag2:
pass #do something here
你可以使用numpy来解决这个问题。
import numpy as np
def diagonal(arr):
d = np.diag(a)
set_len = len(set(d))
d_len = len(d)
if set_len < d_len:
return False
else:
return True
a = np.array([[1, 0, 1], [0, 0, 0], [0, 0, 1]])
print(diagonal(a))
我有一个库。检查诊断和诊断功能! https://github.com/dhilst/funcyou/blob/master/funcyou/indexers.py
你可以先想办法命名对角线。例如,在 3x3 矩阵中,索引 (x, y) 如下所示:
(0,0) (1,0) (2,0)
(0,1) (1,1) (2,1)
(0,2) (1,2) (2,2)
如果我们沿着对角线走,它们的索引有一个简单的模式。 运行 从左下角到右上角的对角线是:
Diag #1 (0,0)
Diag #2 (0,1) (1,0)
Diag #3 (0,2) (1,1) (2,0)
Diag #4 (1,2) (2,1)
Diag #5 (2,2)
从左上到右下分别是:
#1 (0,2)
#2 (0,1) (1,2)
#3 (0,0) (1,1) (2,2)
#4 (1,0) (2,1)
#5 (2,0)
请注意,在左下角到右上角的情况下,同一对角线上的每个单元格 (x, y) 都具有相同的 x + y 值。在另一种情况下,同一对角线上的每个单元格都具有相同的 x - y 值。显然这对于任何大小的矩阵都是正确的。我们可以使用 x+y 和 x-y 来命名各个对角线。当我们遍历矩阵时,每次遇到“1”时,我们都可以立即计算出在那里相交的两条对角线的名称。
这提出了一种有效的算法来确定是否有任何两个“1"s are on the same diagonal. In Python we can use two sets to keep track of the "占用”对角线。如果我们在已经被占用的对角线上遇到“1”,我们 return 为真,否则为假。只要我们访问所有元素,我们就可以按任何顺序遍历矩阵。
def has_diagonal_ones(a):
# a is a 2-dimensional square array of 0's and 1's
lower_left_upper_right = set()
upper_left_lower_right = set()
for x in range(len(a)):
for y in range(len(a)):
if a[x][y] == 0:
continue
i_lower_to_upper = x + y
i_upper_to_lower = x - y
if i_lower_to_upper in lower_left_upper_right:
return True
if i_upper_to_lower in upper_left_lower_right:
return True
lower_left_upper_right.add(i_lower_to_upper)
upper_left_lower_right.add(i_upper_to_lower)
return False
L = [[1, 0, 1],
[0, 0, 0],
[0, 0, 1]]
print(has_diagonal_ones(L))
>>> True
我有一个 0 和 1 的嵌套列表,例如:
L = [[1, 0, 1],
[0, 0, 0],
[0, 0, 1]]
我想检查是否有任何对角线。嵌套列表可以有任何大小,只要子列表的长度等于整个列表的长度(它是一个正方形)。因此,如果我 运行 它在上面的列表中,它将 return 错误,因为两个是对角线。
我当前的代码是:
for num, i in enumerate(List):
for count, m in enumerate(i):
key1 = True
key2 = True
key3 = True
key4 = True
num1 = num
num2 = num
num3 = num
num4 = num
count1 = count
count2 = count
count3 = count
count4 = count
if m == 1:
while key1 or key2 or key3 or key4:
#print(key1, key2, key3, key4)
try:
if List[num1 + 1][count1 + 1] == 1:
print(List[num1 + 1][count1 + 1])
return False
num1 += 1
count1 += 1
except IndexError:
key1 = False
try:
if List[num2 - 1][count2 + 1] == 1:
if num2 > 0:
print(List[num2 - 1][count2 + 1])
return False
num2 -= 1
count2 += 1
except IndexError:
key2 = False
try:
if List[num3 + 1][count3 - 1] == 1:
if count3 > 0:
print(List[num3 + 1][count3 - 1])
print(num3 + 1, count3 - 1)
return False
num3 += 1
count3 -= 1
except IndexError:
key3 = False
try:
if List[num4 - 1][count4 - 1] == 1:
if count4 > 0 and num4 > 0:
print(List[num4 - 1][count4 - 1])
return False
num4 -= 1
count4 -=1
except IndexError:
key4 = False
return True
代码扫描列表 1 秒,当找到一个时,它会查看它的四个角并搜索它们。它继续向拐角的方向搜索,一次移动一格。如果找到另一个 1,则 return 为假。一旦搜索了所有可能的对角线网格(最多 returning 索引错误),代码将移动到找到的下一个 1。一旦搜索到每个 1 并且其中 none 找到任何对角线,则代码 return 为真。
感觉笨重且效率低下,但我不确定如何压缩它。有更短的方法吗?
您可以像这样访问对角线:
L = [[1, 0, 1],
[0, 0, 0],
[0, 0, 1]]
diag1 = [L[i][i] for i in range(len(L))]
diag2 = [L[i][len(L[0])-i-1] for i in range(len(L))]
if diag1 == diag2:
pass #do something here
你可以使用numpy来解决这个问题。
import numpy as np
def diagonal(arr):
d = np.diag(a)
set_len = len(set(d))
d_len = len(d)
if set_len < d_len:
return False
else:
return True
a = np.array([[1, 0, 1], [0, 0, 0], [0, 0, 1]])
print(diagonal(a))
我有一个库。检查诊断和诊断功能! https://github.com/dhilst/funcyou/blob/master/funcyou/indexers.py
你可以先想办法命名对角线。例如,在 3x3 矩阵中,索引 (x, y) 如下所示:
(0,0) (1,0) (2,0)
(0,1) (1,1) (2,1)
(0,2) (1,2) (2,2)
如果我们沿着对角线走,它们的索引有一个简单的模式。 运行 从左下角到右上角的对角线是:
Diag #1 (0,0)
Diag #2 (0,1) (1,0)
Diag #3 (0,2) (1,1) (2,0)
Diag #4 (1,2) (2,1)
Diag #5 (2,2)
从左上到右下分别是:
#1 (0,2)
#2 (0,1) (1,2)
#3 (0,0) (1,1) (2,2)
#4 (1,0) (2,1)
#5 (2,0)
请注意,在左下角到右上角的情况下,同一对角线上的每个单元格 (x, y) 都具有相同的 x + y 值。在另一种情况下,同一对角线上的每个单元格都具有相同的 x - y 值。显然这对于任何大小的矩阵都是正确的。我们可以使用 x+y 和 x-y 来命名各个对角线。当我们遍历矩阵时,每次遇到“1”时,我们都可以立即计算出在那里相交的两条对角线的名称。
这提出了一种有效的算法来确定是否有任何两个“1"s are on the same diagonal. In Python we can use two sets to keep track of the "占用”对角线。如果我们在已经被占用的对角线上遇到“1”,我们 return 为真,否则为假。只要我们访问所有元素,我们就可以按任何顺序遍历矩阵。
def has_diagonal_ones(a):
# a is a 2-dimensional square array of 0's and 1's
lower_left_upper_right = set()
upper_left_lower_right = set()
for x in range(len(a)):
for y in range(len(a)):
if a[x][y] == 0:
continue
i_lower_to_upper = x + y
i_upper_to_lower = x - y
if i_lower_to_upper in lower_left_upper_right:
return True
if i_upper_to_lower in upper_left_lower_right:
return True
lower_left_upper_right.add(i_lower_to_upper)
upper_left_lower_right.add(i_upper_to_lower)
return False
L = [[1, 0, 1],
[0, 0, 0],
[0, 0, 1]]
print(has_diagonal_ones(L))
>>> True