The human Approach
I think my approach to this is different enough from different answers to share.
I am only doing 3 comparisons for every list element so it should be O(n). Also I'm not creating a entirely new list with (value, indices) tuple of all the elements.
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))
Output:
[(0.33, (2, 1)), (0.9, (4, 1)), (1.2, (2, 0))]
The practical approach (Numpy)
If you're familiar with numpy than this is the way to go. Even if you're not it can be use as a copy-paste snippet.
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) )
Output:
least three values : [0.33 0.9 1.2 ]
indices : (2, 1) (4, 1) (2, 0)
See this Stackoverflow query for detailed answer on this.