我有一个函数,它应该将矩阵奇数行中的每个元素递增5,偶数行中的每个元素递增10.我编写了下面的代码:
def incrementRows(matrix):
for i in matrix:
print(matrix.index(i))
if matrix.index(i) % 2 == 0:
matrix[matrix.index(i)] = [x + 5 for x in matrix[matrix.index(i)]]
else:
matrix[matrix.index(i)] = [x + 10 for x in matrix[matrix.index(i)]]
return matrix
matrix = [[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15]]
print(incrementRows(matrix))
这段代码的问题在于,通过函数中的print(matrix.index(i))语句判断,循环从不传递列表中的第一项。我不明白为什么。以下是输出:
0
0
0
[[16, 17, 18, 19, 20], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]]
如果我从函数中取出If / else语句,那么循环将正确迭代列表中的每个项目。
def incrementRows(matrix):
for i in matrix:
print(matrix.index(i))
return matrix
matrix = [[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15]]
print(incrementRows(matrix))
结果:
0
1
2
[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]]
有人能告诉我为什么函数中的If / else语句阻止循环遍历列表中的每个项目吗?
答案 0 :(得分:2)
根据您提供的数据,您将在每一步更改矩阵,以确保始终在索引0处找到其中的下一项。
要检查,请更改
print(matrix.index(i))
到
print(i, matrix, matrix.index(i))
你会看到更多信息量的输出:
[1, 2, 3, 4, 5] [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]] 0
[6, 7, 8, 9, 10] [[6, 7, 8, 9, 10], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]] 0
[11, 12, 13, 14, 15] [[11, 12, 13, 14, 15], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]] 0
请参阅?每次,您都要更改第0个索引,使其等于矩阵中的下一个项目。
循环列表的项目,然后对列表中的每个项目进行.index
,当然,总会找到第一次出现的每个项目的副本 - 除了浪费在任何情况下进行大量计算(制作一个O(N平方)的循环当然应该是O(N))这会在像你这样的情况下引起真正奇怪的结果。
要恢复理智,请更改部分:
def incrementRows(matrix):
for i in matrix:
print(matrix.index(i))
to,例如
def incrementRows(matrix):
for where in range(len(matrix)):
print(where)
并在其他任何地方使用where
,无论你现在正在重新计算(浪费可笑的循环次数)matrix.index(i)
。
答案 1 :(得分:1)
问题在于,在第二次迭代中,第一项和第二项比较相等,因此索引只会再次为您提供第一项。
我相信是时候了解enumerate()了。基本上这里i
只是索引而不必一遍又一遍地扫描列表中的匹配。
def incrementRows(matrix):
for i, item in enumerate(matrix):
print(i)
if i % 2 == 0:
matrix[i] = [x + 5 for x in item]
else:
matrix[i] = [x + 10 for x in item]
return matrix
matrix = [[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15]]
print(incrementRows(matrix))
代码更容易阅读,现在可以正常使用
答案 2 :(得分:1)
这里使用list-comp会更加直截了当,并将模数基于你在条件表达式中迭代的“行号”,以选择添加5或10,例如:
matrix = [[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15]]
result = [
[n + 5 if rowno % 2 == 0 else n + 10 for n in row]
for rowno, row in enumerate(matrix)
]
# [[6, 7, 8, 9, 10], [16, 17, 18, 19, 20], [16, 17, 18, 19, 20]]
答案 3 :(得分:0)
首先,你在迭代它时修改列表的结构。 Don't do that
但我认为你这样做是因为你没有意识到这是做什么的:
for i in matrix:
print(matrix.index(i))
我不知道你是否意识到这一点,但i
将成为迭代中该循环列表中的元素。一个例子:
matrix = [[1,2],[3,4],[5,6]]
for row in matrix:
print(row)
输出:
[1,2]
[3,4]
[5,6]
使用简单的线性搜索,matrix.index(i)
将导致列表i
中的'值'matrix
的索引。
如果你想在索引上使用“c-style”for循环,你可以这样做:
for i in xrange(len(matrix)): # Use just range(len(matrix)) if python 3.X
print(matrix[i])
然而,python有一个漂亮的方法enumerate
,它将为迭代器中的某个位置提供索引和值。
在这种情况下,您的代码将变为以下内容:
def increment_rows(matrix):
for i,row in enumerate(matrix):
print(i,row)
matrix[i] = [v + 5 for v in row] if i % 2 else [v + 10 for v in row]
print(matrix)
return matrix
这将产生您想要的输出。当然,您实际上可以将其合并为一个单行列表,并使用enumerate
:
def increment_rows(matrix):
return [([v + 5 for v in row] if i % 2 else [v + 10 for v in row]) for i,row in enumerate(matrix)]