Python 在二维矩阵中查找值的索引

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17385419/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 08:03:59  来源:igfitidea点击:

Find indices of a value in 2d matrix

pythonoptimizationmatrix

提问by

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

我想获得例如 9 的索引,该索引位于 (2,2)。

What I have tried to do so far.

到目前为止我尝试做的事情。

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

Is there a better way of doing the same. Optimization, anyone? Thanks in advance.

有没有更好的方法来做同样的事情。优化,有人吗?提前致谢。

采纳答案by Ryan Haining

If you want all of the locations that the value appears at, you can use the following list comprehension with valset to whatever you're searching for

如果您想要该值出现的所有位置,您可以使用以下列表理解并val设置为您要搜索的任何内容

[(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.

这不是真的,这会得到所有的出现,它只会得到给定行中第一次出现的值。

回答by mtahmed

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 jwhich could be O(n^2)in the worst case.

这将需要确切的时间i * dim(matrix) + (j+1),在最坏的情况下,上述结果i j可能会O(n^2)出现。

回答by martineau

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.

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

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

回答by rtrwalker

If you convert mymatrix to a numpy array you can jsut use numpy.where to return the indices:

如果将 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]))

回答by ayush thakur

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.

如果您想在 2d 列表中查找所有 val 或字符出现的索引,此代码可能对您有所帮助并且它是可读的。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.

你也可以找到多次出现。