Tazza2092
Tazza2092

Reputation: 61

How to tell when more than one index matches?

I have any array of values, that are often the same and I am trying to find the index of the smallest one. But I want to know all the objects that are the same.

So for example I have the array a = [1, 2, 3, 4] and to find the index of the smallest one I use a.index(min(a)) and this returns 0. But if I had an array of a = [1, 1, 1, 1], using the same thing would still return 0.

I want to know that multiple indices match what I am searching for and what those indices are. How would I go about doing this?

Upvotes: 2

Views: 1566

Answers (3)

vaultah
vaultah

Reputation: 46593

list.index(value) returns the index of the first occurrence of value in list.

A better idea is to use a simple list comprehension and enumerate:

indices = [i for i, x in enumerate(iterable) if x == v]

where v is the value you want to search for and iterable is an object that supports iterator protocol e.g. it can be a generator or a sequence (like list).

For your specific use case, that'll look like

def smallest(seq):
    m = min(seq)
    return [i for i, x in enumerate(seq) if x == m]

Some examples:

In [23]: smallest([1, 2, 3, 4])
Out[23]: [0]

In [24]: smallest([1, 1, 1, 1])
Out[24]: [0, 1, 2, 3]

If you're not sure whether the seq is empty or not, you can pass the default=-1 (or some other value) argument to min function (in Python 3.4+):

m = min(seq, default=-1)

Consider using m = min(seq or (-1,)) (again, any value) instead, when using older Python.

Upvotes: 6

Jakob
Jakob

Reputation: 20831

A different approach using numpy.where could look like

In [1]: import numpy as np
In [2]: def np_smallest(seq):
   ...:     return np.where(seq==seq.min())[0]

In [3]: np_smallest(np.array([1,1,1,1]))
Out[3]: array([0, 1, 2, 3])

In [4]: np_smallest(np.array([1,2,3,4]))
Out[4]: array([0])

This approach is slighly less efficient than the list comprehension for small list but if you face large arrays, numpy may save you some time.

In [5]: seq = np.random.randint(100, size=1000)
In [6]: %timeit np_smallest(seq)
100000 loops, best of 3: 10.1 µs per loop
In [7]: %timeit smallest(seq)
1000 loops, best of 3: 194 µs per loop

Upvotes: 1

Artem
Artem

Reputation: 145

Here is my solution:

def all_smallest(seq):
    """Takes sequence, returns list of all smallest elements"""
    min_i = min(seq)
    amount = seq.count(min_i)
    ans = []
    if amount > 1:
        for n, i in enumerate(seq):
            if i == min_i:
                ans.append(n)
            if len(ans) == amount:
                return ans            
    return [seq.index(min_i)]

Code very straightforward I think here all clear without any explanation.

Upvotes: 0

Related Questions