1

I need to get all the indexes from the smallest elements of this list :

A = [5,2,1,5,6,1,7,9,2]


minimo = min(A)
#print minimo
indexArray = []
for elem in A:
    #print elem
    if elem == minimo:
        indexArray.append(A.index(elem))
print indexArray

need this output : [2,5] but it prints : [2,2]

  • In the case of the duplicate, just check for `== min(A)`. – roganjosh Nov 18 '17 at 12:00
  • 1
    `index` only gives you the first occurrence. – bhansa Nov 18 '17 at 12:10
  • **index** is a function that returns the **_first_** index of an element inside a sequence and that is why the elements in the resulting list are the same number. –  Nov 18 '17 at 12:40

3 Answers3

2

You can use a list-comprehension with enumerate(). With thanks to @MikeScotty, a performance improvement would be to calculate the smallest value first.

Here's the code:

mn = min(A)
[i for i,e in enumerate(A) if e == mn]

which gives:

[2, 5]

which are the indexes of the 1s in A - not [2, 8]


To prove this is faster, here's the minx wrapper:

>>> def minx(l):
...     print("called")
...     return min(l)
... 
>>> [i for i,e in enumerate(A) if e == minx(A)]
called
called
called
called
called
called
called
called
called
[2, 5]

And some timings using timeit:

>>> timeit.timeit("[i for i,e in enumerate(A) if e == min(A)]", globals=locals())
5.9568054789997404
>>> timeit.timeit("[i for i,e in enumerate(A) if e == 1]", globals=locals())
1.397674421001284
Joe Iddon
  • 20,101
  • 7
  • 33
  • 54
  • 1
    This will call ``min`` for each element, which can eat some performance with huge list. better get the smallest element outside of the list-comprehension, even if it means to have 2 lines instead of 1 – Mike Scotty Nov 18 '17 at 12:03
  • @MikeScotty I will update the answer, but it would be interesting to see if `Python` *really* re-evaluates it. I'm not sure and can't find the answer through google, does it really? – Joe Iddon Nov 18 '17 at 12:06
  • 1
    Yes, you can test it if you build your own ``minX(L)`` method as wrapper for ``min()`` and print out if it gets called - you will see it gets called for each iteration. – Mike Scotty Nov 18 '17 at 12:09
  • you can use `%timeit` to check the execution time, is using ipython or notebooks. – bhansa Nov 18 '17 at 12:13
  • @bhansa Good suggestion, updated the answer! – Joe Iddon Nov 18 '17 at 12:16
0

You can try this one too:

A = [5,2,1,5,6,1,7,9,2]
minimum = min(A)
res = list(filter(lambda m: A[m]==minimum, range(len(A))))
print(res)

The output is:

[2, 5]
Vasilis G.
  • 7,556
  • 4
  • 19
  • 29
  • 1
    A solid justification for implementing list comprehensions into the language :) – roganjosh Nov 18 '17 at 12:08
  • 1
    @roganjosh I agree that list comprehension is more readable than using `filter`. I just presented it as an alternative way, just in case. – Vasilis G. Nov 18 '17 at 12:10
0

because when you use

A.index(elem)

it's equal with A.index(1) and the index of 1 will always be 2. You can try this script:

A=[5,2,1,5,6,1,7,9,2]
minimo = min(A)
indexArray = []
for index,value in enumerate(A):
    if value == minimo:
        indexArray.append(index)
print(indexArray)
Hejun
  • 366
  • 2
  • 9