如何在矩阵中找到最小的 3 个值

Posted

技术标签:

【中文标题】如何在矩阵中找到最小的 3 个值【英文标题】:How to find lowest 3 values in a matrix 【发布时间】:2021-04-27 21:31:28 【问题描述】:

所以我有这个功能来找到矩阵中的最小值,并返回它在矩阵中的位置,即它的索引:

final_matrix=[[3.57 2.71 9.2 5.63]
              [4.42 1.4 3.53 8.97]
              [1.2 0.33 6.26 7.77]
              [6.36 3.6 8.91 7.42]
              [1.59 0.9 2.4 4.24]] # this changes in my code, im just giving a very simple version of it here

def lowest_values(final_matrix):
best_value=10000 #or any arbitrarily high number 
    for i in range(0,len(final_matrix[:,0])):
        for j in range(0,len(final_matrix[0,:])):
            if final_matrix[i,j]<best_value:
                best_value=final_matrix[i,j]
                lowest_val_i=i
                lowest_val_j=j
    return(lowest_val_i, lowest_val_j)

这返回我 (1,2),仅通过视觉分析是正确的。我现在想找到最低的 3 个值 - 希望能够构建到这个循环中。但我真的想不出怎么办!或者至少我不知道如何实现它。我在想一些 if-else 循环,如果已经找到最低值,那么“无效”这个值并找到第二个最低值,然后同样找到第三个值。但我不确定。

请不要太快结束这个问题 - 我对编程很陌生,而且非常卡住!

【问题讨论】:

final_matrix[0,:] 无效。 0, 是一个元组。怎么回你(1, 2) final_matrix 实际上是一个二维 numpy 数组吗? 从目前的 PO 来看,我怀疑他正在寻找 numpy 解决方案。不是纯 Python。 【参考方案1】:

人性化的方法

我认为我对此的处理方式与分享的不同答案有很大不同。

我只对每个列表元素进行 3 次比较,所以它应该是 O(n)。此外,我不会创建一个包含所有元素的 (value, indices) 元组的全新列表。

matrix=[[3.57, 2.71, 9.2, 5.63],
              [4.42, 1.4, 3.53, 8.97],
              [1.2, 0.33, 6.26, 7.77],
              [6.36, 3.6, 8.91, 7.42],
              [1.59, 0.9, 2.4, 4.24]]
              
            
def compare_least_values(value, i, j):
    global least
    if value < least[2][0] :
        if value < least[1][0] :
            if value < least[0][0] :
                least.insert(0, (value,(i,j)))
            else:
                least.insert(1, (value,(i,j)))
        else:
            least.insert(2, (value,(i,j)))
    

def lowest_three_values(matrix): 
    global least
    least = [(10000, (None, None)), (10000, (None, None)), (10000, (None, None))]  
    for i, row in enumerate(matrix):
        for j, value in enumerate(row):
            compare_least_values(value, i, j)
    return least[:3]
    
print(lowest_three_values(matrix))

输出:

[(0.33, (2, 1)), (0.9, (4, 1)), (1.2, (2, 0))]

实用方法(Numpy)

如果您熟悉 numpy,那么这就是您要走的路。即使你不是,它也可以用作复制粘贴 sn-p。

import numpy as np

matrix=[[3.57, 2.71, 9.2, 5.63],
              [4.42, 1.4, 3.53, 8.97],
              [1.2, 0.33, 6.26, 7.77],
              [6.36, 3.6, 8.91, 7.42],
              [1.59, 0.9, 2.4, 4.24]]
matrix = np.array(matrix)

indices_1d = np.argpartition(matrix, 3, axis=None)[:3]
indices_2d = np.unravel_index(indices_1d, matrix.shape)
least_three = matrix[indices_2d]

print('least three values : ', least_three)
print('indices : ', *zip(*indices_2d) )

输出:

least three values :  [0.33 0.9  1.2 ] 
indices :  (2, 1) (4, 1) (2, 0)

请参阅此*** query 以获取有关此问题的详细答案。

【讨论】:

【参考方案2】:

您正在从项目列表(或本例中的“矩阵”)中寻找 N 个最小的项目,当 N 较小时,您可以比通过创建 heap queue 对列表中的项目进行排序更好,这需要线性时间,然后弹出 N 个最小元素,这是每个弹出的 O(log N) 操作。 heap queue 是一个重要的数据结构,你应该学习一下。

import heapq

final_matrix=[[3.57, 2.71, 9.2, 5.63],
              [4.42, 1.4, 3.53, 8.97],
              [1.2, 0.33, 6.26, 7.77],
              [6.36, 3.6, 8.91, 7.42],
              [1.59, 0.9, 2.4, 4.24]]

def lowest_values(final_matrix):
    # create a flat list, l, from the matrix
    # each element is a tuple: (value, x-coordinate, y-coordinate)
    l = [(final_matrix[x][y], x, y)
        for x in range(len(final_matrix))
            for y in range(len(final_matrix[0]))
        ]
    heapq.heapify(l) # O(N) time
    for _ in range(3):
        # pop next smallest tuple:
        value, x, y = heapq.heappop(l) # O(log N) time
        print(f'value=value, x=x, y=y')

lowest_values(final_matrix)

打印:

value=0.33, x=2, y=1
value=0.9, x=4, y=1
value=1.2, x=2, y=0

注意

上面的代码可以简化为下面的代码,如果你想要的只是 3 个最小的项目,然后你不再需要堆队列结构,这可能会更有效。但我想展示从列表创建堆队列然后从该堆队列中连续生成最小项的两个基本操作:

import heapq

final_matrix=[[3.57, 2.71, 9.2, 5.63],
              [4.42, 1.4, 3.53, 8.97],
              [1.2, 0.33, 6.26, 7.77],
              [6.36, 3.6, 8.91, 7.42],
              [1.59, 0.9, 2.4, 4.24]]

def lowest_values(final_matrix):
    # create a flat list, l, from the matrix
    # each element is a tuple: (value, x-coordinate, y-coordinate)
    l = [(final_matrix[x][y], x, y)
        for x in range(len(final_matrix))
            for y in range(len(final_matrix[0]))
        ]
    for value, x, y in heapq.nsmallest(3, l):
        print(f'value=value, x=x, y=y')

lowest_values(final_matrix)

【讨论】:

【参考方案3】:

这是我的解决方案:

final_matrix=[[3.57, 2.71, 9.2, 5.63],
              [4.42, 1.4, 3.53, 8.97],
              [1.2, 0.33, 6.26, 7.77],
              [6.36, 3.6, 8.91, 7.42],
              [1.59, 0.9, 2.4, 4.24]]

min_values = []
for i in range(3):
    mini = final_matrix[0][0]
    for row in final_matrix:
        for n in row:
            if n < mini:
                mini = n
                n_index = row.index(n)
                row_index = final_matrix.index(row)
    min_values.append(mini)
    del final_matrix[row_index][n_index]


print("Finals ".format(min_values))

让我解释一下: 第一个循环通过你想要多少最小值(改变它,你会明白我的意思) 第二个和最后一个,遍历矩阵以获取最小值 del final_matrix[row_index][n_index] 行将破坏原始矩阵中的最小数 因此,如果您想保留原始矩阵,则必须创建一个新矩阵并将原始矩阵复制到 => 使用复制模块中的 deepcopy()

【讨论】:

【参考方案4】:

我不明白返回的东西 (1,2)。矩阵的最小值为 0.33。那个位置是(2,1)。

所以我的代码解决方案;

all_items = []
# i appended matrix's all items to one list
for row in final_matrix:
    for i in row:
        all_items.append(i)
# and i sorted that list as from min to max
all_items.sort()
# then i took first 3 values
lowest_3 = all_items[0:3]
positions = []
# and i append their positions that's in the matrix into positions
for i in lowest_3:
    for row in range(len(final_matrix)):
        if(i in final_matrix[row]):
            positions.append([row, final_matrix[row].index(i)])
            break

# lowest_3  = [0.33, 0.9, 1.2]
# positions = [[2, 1], [4, 1], [2, 0]]


【讨论】:

以上是关于如何在矩阵中找到最小的 3 个值的主要内容,如果未能解决你的问题,请参考以下文章

如何在给定范围内找到数组中的最小值?

如何在numpy矩阵中找到最小值?

如何优化矩阵中行 x 列组合的搜索?

矩阵列的最小元素

在python中找到二维矩阵(二维)中不同列表的最小值、最大值和平均值

如何在列中找到第二个值