user62089
user62089

Reputation: 561

Getting all the min elements and its indices from a list

I have a list that has a minimum element that is present multiple times like

a = [1,2,1,1,4,5,6]

And I want Python to return the element 1 and all the indices in the list where 1 is present. I tried using

min_index, min_value = min(enumerate(a), key=operator.itemgetter(1))

which gives only the index where 1 occurs first.

Upvotes: 12

Views: 19563

Answers (3)

Ryan Haining
Ryan Haining

Reputation: 36782

determine the minimum element, and then check it against other elements in the list.

def locate_min(a):
    smallest = min(a)
    return smallest, [index for index, element in enumerate(a) 
                      if smallest == element]

which will return a tuple (min_element, [location, location, ...]). If I understand you correctly, this is what I think you want. For your example:

>>> locate_min([1, 2, 1, 1, 4, 5, 6])
(1, [0, 2, 3])

This example uses a list comprehension. If you're not familiar with this, it's roughly equivalent to the following for-loop version. (use the first version, this is just to help your understanding of how it works)

def locate_min(a):
    min_indicies = []
    smallest = min(a)
    for index, element in enumerate(a):
        if smallest == element: # check if this element is the minimum_value
            min_indicies.append(index) # add the index to the list if it is

    return smallest, min_indicies

Upvotes: 17

Guy Gangemi
Guy Gangemi

Reputation: 1773

The examples given loop through the list twice, once to find the min and again to find all that match it. In the case where the comparison is expensive or it's a very large data set, you may wish to perform a single loop. Here's an example how:

def locate_min(a):
    enumerated_iter = enumerate(a)

    index, min_value = next(enumerated_iter)
    indexes = [index]

    for index, value in enumerated_iter:
        if value == min_value:
            indexes.append(index)
        elif value < min_value:
            min_value = value
            indexes = [index]

    return min_value, indexes

enumerate is an iterator. This allows the use of next to 'pop' the first value from the sequence to prime the search. It can then be used in a for loop to continue on.

Upvotes: 1

Blender
Blender

Reputation: 298096

I'd just do it like this:

minimum = min(a)
indices = [i for i, v in enumerate(a) if v == minimum]

Upvotes: 20

Related Questions