I have a matrix of the form,
mymatrix=[[1,2,3],[4,5,6],[7,8,9]]
I want to the get the index of, say for example, 9 which is at (2,2).
if you want to find the index of all the occurrence of a val or character in a 2d list, this code may help you and it's readable. Tnq.
for i, e in enumerate(board):
for j, ee in enumerate(e):
if 'd' in ee:
print(i, j)
you can find multiple occurrences too.
I think you may find the following useful, enlightening, and maybe even surprising:
Edit: Moved target value to middle of matrix to simulate average location if the data are random and level the playing field for algorithms that stop as soon as it is found.
Also ran timings under both Python 2 & 3 for comparison.
from __future__ import print_function
import sys
import timeit
setup = """
mymatrix=[[1,2,3],[4,9,6],[7,8,5]] # moved target value to middle
val = 9
"""
statements = {
"Anuk (OP)": """
# finds all occurrences
found = []
for i,j in enumerate(mymatrix):
for k,l in enumerate(j):
if l==val:
found.append((i,k))
""",
"Ryan Haining": """
# only finds first occurrence in each row
found = [(index, row.index(val)) for index, row in enumerate(mymatrix) if val in row]
""",
"martineau": """
# finds all occurrences
width = len(mymatrix[0])
found = []
posn = 0
for row in mymatrix:
for col in row:
if col == val:
found.append((posn // width, posn % width))
posn += 1
""",
"martineau #2": """
# finds all occurrences
width = len(mymatrix[0])
found = [(posn // width, posn % width)
for posn,elem in enumerate(col for row in mymatrix for col in row)
if elem == val]
""",
"mtahmed": """
# stops after it finds first occurrence
matrix_dim = len(mymatrix[0])
item_index = 0
for row in mymatrix:
for i in row:
if i == val:
break
item_index += 1
if i == val:
break
found = [(int(item_index / matrix_dim), item_index % matrix_dim)]
""",
}
N = 1000000
R = 3
timings = [
(idea,
min(timeit.repeat(statements[idea], setup=setup, repeat=R, number=N)),
) for idea in statements]
longest = max(len(t[0]) for t in timings) # length of longest name
print('fastest to slowest timings (Python {}.{}.{})\n'.format(*sys.version_info[:3]),
' ({:,d} executions, best of {:d})\n'.format(N, R))
ranked = sorted(timings, key=lambda t: t[1]) # sort by speed (fastest first)
for timing in ranked:
print("{:>{width}} : {:.6f} secs, rel speed {rel:>8.6f}x".format(
timing[0], timing[1], rel=timing[1]/ranked[0][1], width=longest))
Sample output:
fastest to slowest timings (Python 2.7.5)
(1,000,000 executions, best of 3)
mtahmed : 2.850508 secs, rel speed 1.000000x
martineau : 3.684153 secs, rel speed 1.292455x
Ryan Haining : 8.391357 secs, rel speed 2.943811x
Anuk (OP) : 14.014551 secs, rel speed 4.916510x
martineau #2 : 15.880949 secs, rel speed 5.571270x
fastest to slowest timings (Python 3.3.2)
(1,000,000 executions, best of 3)
mtahmed : 5.019435 secs, rel speed 1.000000x
martineau : 5.217747 secs, rel speed 1.039509x
Ryan Haining : 5.705710 secs, rel speed 1.136723x
Anuk (OP) : 8.317911 secs, rel speed 1.657141x
martineau #2 : 11.590270 secs, rel speed 2.309078x
You could do this instead of using enumerate. NOT sure at all if this is any faster.
matrix = [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
needle = 9
matrix_dim = len(matrix[0])
item_index = 0
for row in matrix:
for i in row:
if i == needle:
break
item_index += 1
if i == needle:
break
print(int(item_index / matrix_dim), item_index % matrix_dim)
This will take exactly time i * dim(matrix) + (j+1)
where the result of the above is i j
which could be O(n^2)
in the worst case.
If you convert mymatrix to a numpy array you can jsut use numpy.where to return the indices:
>>> import numpy as np
>>> mymatrix=[[1,2,3],[4,5,6],[7,8,9]]
>>> a = np.array(mymatrix)
>>> a
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
>>> b = np.where(a==9)
>>> b
(array([2]), array([2]))
>>> mymatrix=[[1,2,3],[9,5,6],[7,8,9]]
>>> a = np.array(mymatrix)
>>> a
array([[1, 2, 3],
[9, 5, 6],
[7, 8, 9]])
>>> b = np.where(a==9)
>>> b
(array([1, 2]), array([0, 2]))
If you want all of the locations that the value appears at, you can use the following list comprehension with val
set to whatever you're searching for
[(index, row.index(val)) for index, row in enumerate(mymatrix) if val in row]
for example:
>>> mymatrix=[[1,2,9],[4,9,6],[7,8,9]]
>>> val = 9
>>> [(index, row.index(val)) for index, row in enumerate(mymatrix) if val in row]
[(0, 2), (1, 1), (2, 2)]
EDIT
It's not really true that this gets all occurrences, it will only get the first occurrence of the value in a given row.