For a rectangular matrix, you can use divmod to ger the row and column indexes Access Complexity: O(1):
matrix = [[1, 2, 3,],
[10,11,12],
[21,22,23]]
r,c = divmod(6,len(matrix[0]))
value = matrix[r][c]
print(value) # 21
For an irregular list of lists, as long as none of the sizes change, you can build an indirection list and use it to convert a flat position into row and column indexes Access Complexity: O(1) Indexing complexity O(N) (N=total number of elements):
matrix = [[1, 2, 3, 4 ,5],
[10,11,12],
[21,22,23,24]]
indx = [ (r,c) for r,row in enumerate(matrix) for c in range(len(row)) ]
pos = 8
r,c = indx[pos]
value = matrix[r][c]
print(value) # 21
Once the indx list is created, accessing elements will be practically as fast as the rectangular matrix method (integer division and modulo).
Note, you would have to recreate the indirection list (indx) any time you change the size of the list or if any of its rows.
If your matrix is changed (in size) more often than you access it using flat positions, you could create a function to return the indexes Access Complexity: O(R):
def rowCol(m,p):
for r,row in enumerate(m):
if p<len(row): return r,p
p-=len(row)
r,c = rowCol(matrix,8)
value = matrix[r][c]
print(value)
This will be a lot slower to access than the prepared indx variable so you may want to use hybrid approach where you clear the index after each change and only rebuild it on demand (when the function is called)
Another alternative that will build the index faster but will be a bit slower to access would be to create an index with only the cumulative sizes of the matrix's rows. You can then use a binary search algorithm to find the row and a simple subtraction to find the column Access Complexity: O(log(R)) Indexing complexity: O(R)
matrix = [[1, 2, 3,],
[10,11,12,13,14],
[21,22,23,24]]
from itertools import accumulate
from bisect import bisect_left
indx = [0]+list(accumulate(map(len,matrix)))
pos = 8
r = bisect_left(indx,pos+1)-1
c = pos - indx[r]
value = matrix[r][c]
print(pos,r,c,value) # 21
This is slower to access than the full coordinate indexing but it will consume less memory and will still be much faster than the iterative function (which essentially does the same thing sequentially)