Reputation: 27
def list_2d_locations(rows, columns, low_range, high_range):
matrix = list_2d_generate(rows, columns, low_range, high_range)
print(matrix)
low_val = high_val = matrix[0][0]
for i in range(rows):
for j in range(columns):
if matrix[i][j] < low_val:
low_val = matrix[i][j]
low_loc = [i][j]
if matrix[i][j] > high_val:
high_val = matrix[i][j]
high_loc = [i][j]
return low_val, high_val, low_loc, high_loc
I have here a function which is supposed to find the smallest and largest number within a list of lists (i.e. a matrix) and return the actual value, and the position of that value within the matrix. Now my problem is that both high_loc = [i][j]
and low_loc = [i][j]
give me the error of "list index out of range" and I don't understand why. Wouldn't the if statements also be out of range then by the same logic?
Upvotes: 0
Views: 114
Reputation: 4184
Here is a solution. It is clean. However, for big matrices it should be optimized to iterate only once over them and collect all info during that iteration.
m = [[3,5,1], [56,43,12], [4,52,673]]
def f(matrix):
cols = len(matrix[0])
flatten = [val for row in matrix for val in row]
min_val, max_val = min(flatten), max(flatten)
min_i, max_i = flatten.index(min_val), flatten.index(max_val)
return min_val, max_val, divmod(min_i, cols), divmod(max_i, cols)
>>> f(m)
(1, 673, (0, 2), (2, 2))
EDIT: You know what, here is the optimized version:
def f(matrix):
try:
min_val, max_val = matrix[0][0], matrix[0][0]
except IndexError:
raise ValueError("Expected a real matrix.") from None
genexp = (val for row in matrix for val in row)
cols = len(matrix[0])
min_i, max_i = (0, 0), (0, 0)
for i, val in enumerate(genexp):
if val < min_val:
min_val, min_i = val, divmod(i, cols)
elif val > max_val:
max_val, max_i = val, divmod(i, cols)
return min_val, max_val, min_i, max_i
EDIT2:
Here are an experience for better understanding which could be done either by you. I suggest you do the same if you want to understand a code.
>>> matrix = [[3,5,1], [56,43,12], [4,52,673]]
>>> flatten = [val for row in matrix for val in row]
>>> flatten
[3, 5, 1, 56, 43, 12, 4, 52, 673]
>>> flatten.index(56)
3
>>> divmod(3,3)
(1, 0)
>>> for elem in enumerate(["one", "two", "three"]):
... elem
...
(0, 'one')
(1, 'two')
(2, 'three')
Upvotes: 1
Reputation: 30561
The problem is in the line low_loc = [i][j]
. In the expression on the right-hand side of the =
sign, [i]
is a list with a single element, and [i][j]
represents an attempt to extract the element at position j
from that list. That will fail unless j == 0
. Perhaps you wanted low_loc = [i, j]
or low_loc = (i, j)
instead? (The same comments apply to the line high_loc = [i][j]
, of course.)
Upvotes: 1