Нахождение координат максимального значения в сетке - PullRequest
1 голос
/ 21 марта 2020

Учитывая сетку чисел типа

g=[[2, 2, 2, 3, 2],
   [2, -1, -1, 3, 3],
   [3, 2, -1, 3, 3],
   [2, 4, 3, 3, 3],
   [-1, 2, 2, -1, 1]]

, я ищу максимальное значение в этом 2-м списке, который, в данном примере, однозначно 4. Чтобы найти это, max(max(graph,key=max)) выполняет свою работу (хотя я знаю, что он вызывает max для строки с максимальным значением дважды, поэтому это не совсем эффективно)

Но это только половина того, что я ищу. Мне нужны координаты этого 4. Я хотел бы иметь короткий, эффективный и pythoni c фрагмент кода, такой как x, y = find_2d_max_index(g), который дает мне позицию максимального числа, не выполняя тройной функции max раньше. Я хочу избежать использования метода index() после нахождения максимума, так как это было бы очень неэффективно.

Я изучил numpy argmax, но не смог заставить его работать в этом приложении с двухмерным списком. .

Любая помощь приветствуется.

Ответы [ 4 ]

1 голос
/ 21 марта 2020

Вы можете использовать numpy для этого, а документация иллюстрирует, как.

import numpy as np

a = np.array([[2, 2, 2, 3, 2],
   [2, -1, -1, 3, 3],
   [3, 2, -1, 3, 3],
   [2, 4, 3, 3, 3],
   [-1, 2, 2, -1, 1]])

idx = np.unravel_index(np.argmax(a), a.shape)

a[idx]
>> 4

Объяснение: Мы используем argmax без оси, определенной для получения индекса максимума item, если бы массив был одним плоским массивом, в этом случае это было бы 16, поскольку число 4 было бы элементом 16th этого длинного массива. Затем мы предоставляем форму нашего фактического массива для np.unravel_index и индекс максимального элемента, в данном случае 16, и он определяет на основе формы массива координаты этого числа.

1 голос
/ 21 марта 2020

Если все «строки» в graph имеют одинаковую длину (что делает graph эквивалентным массиву 2D numpy), то вы можете просто найти положение наибольшего значения в линейном расширении и вывести координаты от позиции и количества «столбцов» в graph (так работает numpy под капотом).

import operator as op
from itertools import chain

ncol = len(graph[0])
flattened = chain.from_iterable(graph)
max_idx, max_val = max(enumerate(flattened), key=op.itemgetter(1))
row = max_idx // ncol
col = max_idx % ncol

# a simple sanity check
assert graph[row][col] == max_val
1 голос
/ 21 марта 2020

вы можете использовать max и enumerate встроенные функции:

(col, val), row = max(map(lambda x: (max(enumerate(x[1]), key= lambda x: x[1]), x[0]), enumerate(g)), key=lambda x: x[0][1])
print(col, row)

выход:

1 3

, чтобы разбить это на части, вы можете использовать:

from typing import List, Tuple

# didn't get the inner functions out to be easy to read/understand
def max_row_with_column_and_row_coordinates(row_list: tuple):
        """Given row number and the value return the max on each row

        with the row number and column number
        """

        def get_max_row(row_list: Tuple[int, List]) -> Tuple[Tuple[int, int], int]:
            row_number, inner_list = row_list
            # will give you the col number and the actual number/value
            col_value = enumerate(inner_list)  # (col_number, number)

            def get_value(col_value: Tuple[int, int]) -> int:
                col_number, value = col_value
                return value

            col_max_row = max(col_value, key=get_value)

            return col_max_row, row_number # ((col_number, value), row_number)

        def get_the_value(col_value_row: Tuple[Tuple[int, int], int]) -> int:
            (col_number, value), row_numebr = col_value_row # unpack
            return value

        max_row_with_coordinates = map(get_max_row, row_list)

        return max(max_row_with_coordinates, key=get_the_value)  # ((col_number, value), row_numebr) 


def max_value_with_coordinates(g: List[List]) -> Tuple[Tuple[int, int], int]:
    """Return the max on each row keeping the coordinates of each value.

    The coordinates are given by the enumerate built-in function.
    """

    row_list = enumerate(g) # will give you the row number: (row_numebr, inner_list)
    return max_row_with_column_and_row_coordinates(row_list) # ((col_number, value), row_numebr) 

(col, val), row = max_value_with_coordinates(g)

print(col, row)

вывод:

1 3
0 голосов
/ 21 марта 2020

Просто сделайте следующее:

max(map(max, graph))

Это вызовет max только один раз для каждой строки, а затем примет максимум из результатов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...