2013-06-29 3 views
4

У меня есть матрица вида,Найти индексы значения в 2d матрицы

mymatrix=[[1,2,3],[4,5,6],[7,8,9]] 

Я хочу к получить индекс, скажем, к примеру, 9, который находится в точке (2,2).

То, что я пытался сделать до сих пор.

for i,j in enumerate(mymatrix): 
    for k,l in enumerate(j): 
    if l==9: 
     print i,k 

Есть ли лучший способ сделать то же самое. Оптимизация, кто-нибудь? Заранее спасибо.

ответ

6

Если вы хотите, чтобы все места, которые появляется значение в, вы можете использовать следующий список понимание с val набора к тому, что вы ищете

[(index, row.index(val)) for index, row in enumerate(mymatrix) if val in row] 

, например:

>>> 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)] 

РЕДАКТИРОВАТЬ

Это не так, потому что это все происходит, оно получит только первое появление значение значения в данной строке.

+0

Это трюк, в наши дни я пытаюсь узнать больше о части оптимизации? Как определить сложность этого кода? Генераторы быстрые. Это то, на что я тоже смотрю .. :) –

+0

Действительно ли вы определили, насколько быстро этот код сравнивается с кодом OP? – Blender

+0

@Blender, я немного замедлил время. Все еще изучая основы ...! Любые указатели там, я буду очень благодарен! –

2

Вы можете сделать это вместо использования перечисления. НЕ уверен, что если это произойдет быстрее.

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) 

Это займет точно время i * dim(matrix) + (j+1), когда результат выше является i j, который может быть в худшем случае O(n^2).

+1

+ 1 Это самый быстрый результат в соответствии с эталоном, выполненным в моем ответе, хотя он останавливается после того, как он находит одно событие. Единственное, что я нашел быстрее, - это установить код, чтобы проверить все возможные позиции в матрице. – martineau

4

Я думаю, вы можете найти следующую полезную, поучительно, и, может быть, даже удивительно:

Edit: Переехал целевое значение до середины матрицы для имитации усредненного местоположения, если данные являются случайными и выровнять игровое поле для алгоритмы, которые останавливаются, как только они будут найдены.

Также использовались тайминги под обоими Python 2 & 3 для сравнения. Выход

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)) 

Пример:

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 
+0

Это действительно интересно узнать. Даже техника тестирования действительно интересна! –

5

Если преобразовать mymatrix в Numpy массива вы можете использовать numpy.where этого нужно просто вернуть показатели:

>>> 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])) 
0

, если вы хотите, чтобы найти индекс всего вхождения символа val или символа в списке 2d, этот код может помочь вам и его можно прочитать. TNQ.

for i, e in enumerate(board): 
    for j, ee in enumerate(e): 
     if 'd' in ee: 
      print(i, j) 

Вы также можете найти несколько случаев.

Смежные вопросы