简体   繁体   中英

How do I find the Index of the smallest number in an array in python if I have multiple smallest numbers and want both indexes?

I have an array in which I want to find the index of the smallest elements. I have tried the following method:

distance = [2,3,2,5,4,7,6]

a = distance.index(min(distance))

This returns 0, which is the index of the first smallest distance. However, I want to find all such instances, 0 and 2. How can I do this in Python?

Use np.where to get all the indexes that match a given value:

import numpy as np

distance = np.array([2,3,2,5,4,7,6])

np.where(distance == np.min(distance))[0]

Out[1]: array([0, 2])

Numpy outperforms other methods as the size of the array grows:

Results of TimeIt comparison test, adapted from Yannic Hamann's code below

                     Length of Array x 7
Method               1       10      20      50     100    1000
Sorted Enumerate     2.47  16.291  33.643                      
List Comprehension  1.058   4.745   8.843  24.792              
Numpy               5.212   5.562   5.931    6.22  6.441  6.055
Defaultdict         2.376   9.061  16.116  39.299              

时序结果图

You may enumerate array elements and extract their indexes if the condition holds:

min_value = min(distance)
[i for i,n in enumerate(distance) if n==min_value]
#[0,2]

Surprisingly the numpy answer seems to be the slowest.

Update: Depends on the size of the input list.

import numpy as np
import timeit
from collections import defaultdict


def weird_function_so_bad_to_read(distance):
    se = sorted(enumerate(distance), key=lambda x: x[1])
    smallest_numb = se[0][1]  # careful exceptions when list is empty
    return [x for x in se if smallest_numb == x[1]]
    # t1 = 1.8322973089525476


def pythonic_way(distance):
    min_value = min(distance)
    return [i for i, n in enumerate(distance) if n == min_value]
    # t2 = 0.8458914929069579


def fastest_dont_even_have_to_measure(np_distance):
    # np_distance = np.array([2, 3, 2, 5, 4, 7, 6])
    min_v = np.min(np_distance)
    return np.where(np_distance == min_v)[0]
    # t3 = 4.247801031917334


def dd_answer_was_my_first_guess_too(distance):
    d = defaultdict(list)  # a dictionary where every value is a list by default

    for idx, num in enumerate(distance):
        d[num].append(idx)  # for each number append the value of the index

    return d.get(min(distance))
    # t4 = 1.8876687170704827


def wrapper(func, *args, **kwargs):
    def wrapped():
        return func(*args, **kwargs)
    return wrapped


distance = [2, 3, 2, 5, 4, 7, 6]

t1 = wrapper(weird_function_so_bad_to_read, distance)
t2 = wrapper(pythonic_way, distance)
t3 = wrapper(fastest_dont_even_have_to_measure, np.array(distance))
t4 = wrapper(dd_answer_was_my_first_guess_too, distance)

print(timeit.timeit(t1))
print(timeit.timeit(t2))
print(timeit.timeit(t3))
print(timeit.timeit(t4))

You can also do the following list comprehension

distance = [2,3,2,5,4,7,6]
min_distance = min(distance)
[index for index, val in enumerate(distance) if val == min_distance]
>>> [0, 2]

We can use an interim dict to store indices of the list and then just fetch the minimum value of distance from it. We will also use a simple for-loop here so that you can understand what is happening step by step.

from collections import defaultdict

d = defaultdict(list) # a dictionary where every value is a list by default

for idx, num in enumerate(distance):
    d[num].append(idx) # for each number append the value of the index

d.get(min(distance)) # fetch the indices of the min number from our dict

[0, 2]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM